jackrabbit-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Marcel Reutegger <marcel.reuteg...@gmx.net>
Subject Re: Problems with concurrent sessions
Date Tue, 19 Jul 2005 09:54:45 GMT
Hi Nicolas,

Looks better now, but there are still cases where the doTransaction() 
method will not be called, though very unlikely: when all three 
tryLock() attempts fail. not very likely but theoretically possible...

regards
  marcel

Nicolas Belisle wrote:
> Hi,
> 
> Thanks again for your comments.
> 
> Here's the second version of my template class. It should resolves the 
> concurrency issues you mentionned :
> 
> package app;
> 
> import javax.jcr.Credentials;
> import javax.jcr.LoginException;
> import javax.jcr.Node;
> import javax.jcr.Repository;
> import javax.jcr.RepositoryException;
> import javax.jcr.Session;
> import javax.jcr.lock.LockException;
> import javax.jcr.observation.Event;
> import javax.jcr.observation.EventIterator;
> import javax.jcr.observation.EventListener;
> 
> public abstract class SerializableTemplate {
> 
>     private Session session;
>     private Node scope;
>     private boolean done = false;
>     private EventListener el;
> 
>     public SerializableTemplate(Repository repository, Credentials cr, 
> String scopePath) throws LoginException, RepositoryException {
>         session = repository.login(cr);
>         scope = session.getRootNode().getNode(scopePath);
>         //scope = session.getNodeByUUID(scope.getUUID());
>     }
> 
>     public abstract void doInTransaction(Session session) throws 
> RepositoryException;
> 
>     public void execute() throws RepositoryException {
>         if (tryLock()) {
>             return;
>         }
> 
>         this.el = new EventListener() {
>             public void onEvent(EventIterator events) {
>                 try {
>                     tryLock();
>                 } catch (RepositoryException e) {
>                     throw new RuntimeException(e);
>                 }
>             }
>         };
>         
> session.getWorkspace().getObservationManager().addEventListener(el, 
> Event.PROPERTY_REMOVED, scope.getPath(), true, null, null, false);
> 
>         //Try again, in case the lock is removed before observer could 
> be put in place
>         tryLock();
>     }
> 
>     private synchronized boolean tryLock() throws RepositoryException {
>         try {
>             if (done) {
>                 return false;
>             }
> 
>             if (!scope.isLocked()) {
>                 scope.lock(true, true);
>                 try {
>                     if (el != null) {
>                         
> session.getWorkspace().getObservationManager().removeEventListener(el);
>                     }
>                     doInTransaction(session);
>                 } finally {
>                     done = true;
>                     if (session.isLive()) {
>                         session.logout();
>                     }
>                 }
>                 return true;
>             }
>         } catch (LockException e) {
>             e.printStackTrace();
>         }
>         return false;
>     }
> }
> 
> Here's how to use it :
> 
> SerializableTemplate sTemplate = new SerializableTemplate(repository, 
> new SimpleCredentials("user", "password".toCharArray()), "node/path") {
>         //@Override
>         public void doInTransaction(Session session) throws 
> RepositoryException {
>                 //Do your favorite transaction...
>         };
> sTemplate.execute();
> 
> 
> For the constructor you suggested, I actually came up with a similiar 
> design at first, but found a problem with it : since the template class 
> might use an EventListener the class should be responsible for closing 
> the session (the EventListener can wait a while...). Else, the event 
> could be removed by the user before being invoked. That's the reason for 
> my ugly constructor.
> 
> I welcome your comments again...
> 
> Regards,
> 
> Nicolas
> 

Mime
View raw message