Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (c) 2010. Axon Framework
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package org.axonframework.repository;
 
 
 import java.util.Map;
Implementation of the LockManager that uses an optimistic locking strategy. It uses the sequence number of the last committed event to detect concurrent access.

Classes that use a repository with this strategy must implement any retry logic themselves. Use the ConcurrencyException to detect concurrent access.

 
 class OptimisticLockManager implements LockManager {
 
     private final ConcurrentHashMap<StringOptimisticLocklocks = new ConcurrentHashMap<StringOptimisticLock>();

    
 
     @Override
     public boolean validateLock(AggregateRoot aggregate) {
         OptimisticLock lock = .get(aggregate.getIdentifier().asString());
         return lock != null && lock.validate(aggregate);
     }

    
 
     @Override
     public void obtainLock(AggregateIdentifier aggregateIdentifier) {
         boolean obtained = false;
         while (!obtained) {
             .putIfAbsent(aggregateIdentifier.asString(), new OptimisticLock());
             OptimisticLock lock = .get(aggregateIdentifier.asString());
             obtained = lock != null && lock.lock();
             if (!obtained) {
                 .remove(aggregateIdentifier.asString(), lock);
             }
         }
     }

    
 
     @Override
     public void releaseLock(AggregateIdentifier aggregateIdentifier) {
         OptimisticLock lock = .get(aggregateIdentifier.asString());
         if (lock != null) {
             lock.unlock(aggregateIdentifier);
         }
     }
 
     private final class OptimisticLock {
 
         private Long versionNumber;
         private Map<ThreadIntegerthreadsHoldingLock = new WeakHashMap<ThreadInteger>();
         private boolean closed = false;
 
         private OptimisticLock() {
         }
 
         private synchronized boolean validate(AggregateRoot aggregate) {
             Long lastCommittedEventSequenceNumber = aggregate.getVersion();
             if ( == null || .equals(lastCommittedEventSequenceNumber)) {
                 long last = lastCommittedEventSequenceNumber == null ? 0 : lastCommittedEventSequenceNumber;
                  = last + aggregate.getUncommittedEventCount();
                 return true;
             }
             return false;
         }
 
         private synchronized boolean lock() {
             if () {
                 return false;
            }
            Integer lockCount = .get(Thread.currentThread());
            if (lockCount == null) {
                lockCount = 0;
            }
            .put(Thread.currentThread(), lockCount + 1);
            return true;
        }
        private synchronized void unlock(AggregateIdentifier aggregateIdentifier) {
            Integer lockCount = .get(Thread.currentThread());
            if (lockCount == null || lockCount == 1) {
                .remove(Thread.currentThread());
            } else {
                .put(Thread.currentThread(), lockCount - 1);
            }
            if (.isEmpty()) {
                 = true;
                .remove(aggregateIdentifier.asString(), this);
            }
        }
    }
New to GrepCode? Check out our FAQ X