11 February, 2014

Access Modifiers in Scala for Java programmers

   Today I’m going to concisely compare Scala's access modifiers with these used in Java. For more detailed description please refer to this post.

Java access modifiers:

Scala access modifiers:


Additionally in Scala private and protected access modifiers can be qualified with a name of a package or class. This is done using square brackets e.g.
For class defined in package a.b.c 
  • protected[c] will be the same as protected in Java
  • private[c] will be the same as default in Java
You can also use other packages that are available in class’s package tree:
  • protected[a] will be visible in subclasses and in packages a, b and c (package a and all its subpackages)
  • private[b] will be visible in packages b and c
  • for class defined in package a.b it is not allowed to define private[c] or protected[c]
Inner class in Scala has access to private members of enclosing class, but enclosing class doesn’t have access to private members of inner class.
class Enclosing {
 private val x = 5
 new Inner().z // value z in class Inner cannot be accessed in Enclosing.this.Inner 
 class Inner {
   private val z = 9
   def out = x + z // no problem
 }
}
If you want to make it work similarly to Java you need to add enclosing class qualifier.
   private[Enclosing] val z = 9

The last scope introduce in Scala that is worth to mention is the object private:
   private[this] val member = 1
which stipulates that the member can only be seen by members called on that same object, not from different objects, even if they are of the same type.

27 January, 2014

Scala Dependency Injection techniques

   Lately I was checking different solutions for dependency injection in Scala (code available here in pl.mariusz.marciniak.di package). Scala DI is vastly described in Real World Scala Dependency Injection artice, so I will just put short summary for each of techniques that I used:

Implicits
   The most obvious solution for injecting dependencies is to add parameters to object’s constructor (you can also do it by defining properties, but in that case your object becomes mutable). Additionally Scala provides you implicit parameters, which can be automatically supplied.
  class Calculator (implicit val dataProvider:DataProvider, implicit val operation:Operation) {
    def calculate(): Int = operation.exec(dataProvider.nextArgument, dataProvider.nextArgument)
  }
  val calc = new Calculator

Here Calculator’s constructor has two arguments marked as implicit. This means that they can be omitted if default objects of the same type are defined. Above implementation will generate compilation error, because these defaults are missing. To provide them we can for example define and import configuration object.
  object AdditionFromFakeDbDataConfig {
    implicit val operation: Operation = new Addition 
    implicit val dataProvider: DataProvider = new FakeDbDataProvider
  }
  import AdditionFromFakeDbDataConfig._
  val calc = new Calculator

Structural typing
   This is Scala feature to provide duck typing in a type-safe manner. Duck typing is a style of typing in which an object's methods and properties determine the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface. In Scala you can achieve that by replacing data type with code block containing all required methods and properties.
Calculator(dataProvider: { val x: Int; val y: Int}, operation: { def exec(a: Int, b: Int): Int}) { ... }
Calculator class requires two arguments to be passed to its constructor. First needs to define two values x and y, and the second one must contains function exec taking two integers and returns integer. For example you can pass two objects:
  object Data {
    val x = 5
    val y = 3
  }
  object Avg {
    def exec(a: Int, b: Int): Int = (a + b) / 2 
  }
This solution gives us opportunity to aggregate all required resources into one object and pass that object into constructor. It is good to remember that Scala's structural typing uses reflection, so one can face some performance problems when he is using this solution vastly. Additional information about Structural Typing can be found on this site.

Cake Pattern
   Cake Pattern is the last method that I want to mention about in this post. Cake Pattern combines few Scala features:
  1. Trait with abstract value
  2. First of all you need to create a namespace using trait, containing all classes that you need to inject e.g. Addition and Multiplication are containted in Operations namespace, additionally there is abstract value defined that need to be instantiate in non-abstract object.  
      trait Operations {
        val operation: Operation
        trait Operation {
          def exec(a: Int, b: Int): Int
        }
    
        class Addition extends Operation {
          def exec(a: Int, b: Int): Int = a + b
        }
    
        class Multiplication extends Operation {
          def exec(a: Int, b: Int): Int = a * b
        }
      }
    

  3. Self type
  4. Self type can be used to access fields or functions of other type which implementation will be mixed in later e.g. CalculatorComponent requires two traits DataProviders and Operations, both of them are in fact namespaces with abstract values: dataProvider and operation, that is why they can be accessed in Calculator class  
      trait CalculatorComponent { this: DataProviders with Operations =>
        val calculator = new Calculator
        class Calculator {
          def calculate(): Int = operation.exec(dataProvider.nextArgument, dataProvider.nextArgument)
        }
      }
    
  5. Mixins
  6. Last step is to combine all components in one object. 
      object AdditionFromFakeDbDataConfig extends CalculatorComponent with Operations with DataProviders {
          val operation = new Addition
          val dataProvider = new FakeDbDataProvider
      }
Additional links

26 September, 2013

SimpleMessageListenerContainer autoStartup and connectLazily properties

   Lately after replacing DefaultMessageListenerContainer with SimpleMessageListenerContainer I spotted that the second one ignores autoStartup setting.
Spring documentation states that SimpleMessageListenerContainer creates a fixed number of JMS sessions at startup and uses them throughout the lifespan of the container, but why this happens before checking the autoStartup flag. I chose to explore source code for an answer.
   Initialization of MessageListenerContainers is done automatically when context starts up, as they implement the Lifecycle interface. It is worth to remember that lazy-init flag is ignored for lifecycle beans.
 Let’s look how the initialization flow looks like:
  • constructor
  • set properties (here auto start-up flag is set)
  • post construct method – if defined
  • doInitialize
  • doStart
Execution of doStart method depends on autoStartup flag which is checked in DefaultLifecycleProcessor.startBeans. Both containers use AbstractJmsListeningContainer’s doStart implementation:
  • default container doesn’t override it at all
  • simple container executes it and after that initializes consumers
  • @Override
    protected void doStart() throws JMSException {
          super.doStart();
          initializeConsumers();
    }
    
doStart establishes shared connection and resume all defined tasks. Default container task creates connection, session and consumer. Simple container doesn’t define any asynchronous tasks, instead it creates all these JMS components synchronously in its doInitialize method. So consumers initialization in doStart method is redundant in this case.

Since Spring 3.1 SimpleMessageListenerContainer has additional property connectLazily,that can be used to skip initialization of JMS components in doInitialize method. When this flag is set to true and autoStartup to false, then message listener container needs to be started manually.

29 July, 2013

SudokuSolver in Scala

    Lately I was preparing for Oracle JPA certification (1Z0-898) and finally succeeded with not very impressive result of 79%. I haven’t spent much time on learning, because I found other more joyful activities related to programming.
After finishing Scala course on coursera.org I spend a lot of time writing some simple apps in that language. Some of them not very useful, unless you want to list all polish names for girls, but one which is solver for Sudoku game I chose to put on GitHub. Maybe I will write some other posts about this program, but for now here is the link.
For those who are interested in 1Z0-898, for my preparation I used Enthuware mocks and read few sections from specification, that were listed as compulsory by authors of that mocks.

20 June, 2013

Operation Logic Executor - Source code

    It will be the last post in this series. If you found anything useful please don't hesitate to leave a comment. You can download last version of source code from GitHub. It's a little bit different than in posts, but the idea stays the same.

Operation Logic Executor - Adding executors

    Last version of the locking mechanism provides easy way to control access to resources before task execution, but it is hard to lock resources at the moment of function invocation. To clear what I mean let’s look at example of 2 tasks executed asynchronously are handled by the same thread pool executor with only one thread.
  • Both tasks (T1, T2) goes to blocking queue.
  • ResourceLockAspect is locking resources of T1.
  • T1 is executed
  • ResourceLockAspect releases resources of T1.
  • ResourceLockAspect is locking resources of T2.
  • T2 is executed
  • ResourceLockAspect releases resources of T2.
If T1 and T2 operate on the same resource, user may want to perform locking at the moment of invocation, to prevent T2 from being added to queue. Adding new wrapping object, on which we will lock resources and then performing operation asynchronously will partially solve the problem. I used the idea of executor to implement this functionality. Executor will be in fact decorator of OperationLogic.
public interface OperationExecutor<T> extends OperationLogic<T> {
    void setOperationLogic(OperationLogic<T> logic);
    OperationLogic<T> getOperationLogic();
}
Here is executor’s implementation example. I set bean’s scope to prototype, but if its only property is OperationLogic object with singleton scope and this property doesn’t change, we could also use singleton scope for executor.
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class TransactionProcessingExecutor implements OperationExecutor<Transaction> {

    private OperationLogic<Transaction> logic;

    @ResourceLock(identifierBuilder = TransactionIdentifierBuilder.class, resourceLocker = TransactionLocker.class, resourceLockerBeanName = "transactionLocker")
    public Future<Boolean> executeOperation(OperationData<Transaction> data) throws OperationFailedException {
        return logic.executeOperation(data);
    }

    @Autowired
    @Qualifier(value = "transactionProcessingLogic")
    public void setOperationLogic(OperationLogic<Transaction> logic) {
        this.logic = logic;
    }

    public OperationLogic<Transaction> getOperationLogic() {
        return logic;
    }
}
When executeOperation is invoked resources are locked and then injected operation is performed. If that operation is asynchronous, the invocation will occur and resources will be immediately released. This is why I previously wrote that current executor implementation only partially solve the problem. What I’m going to do is defining AsynOperationLogic with special method operationFinished invoked by aspect when executeOperation method returns
public interface AsyncOperationLogic<T> extends OperationLogic<T> {
    
    public void operationFinished();
    
    public void setResourceReleaser(ResourceReleaser releaser);
    
}
It also contains setter method to define object that will take care of releasing resources.
@Aspect
@Component
public class ReleaseResourcesAspect {

    private Logger             logger = LogManager.getLogger(ReleaseLockAspect.class);

    @After("execution(* pl.mariusz.marciniak.operations.logic.AsyncOperationLogic.executeOperation(pl.mariusz.marciniak.operations.data.OperationData))")
    private void release(JoinPoint jp) {
        logger.debug("releasing resources");
        ((AsyncOperationLogic<?>)jp.getTarget()).operationFinished();
    }


}
Now I need to provide identifiers and locking mechanism that were used for locking to AsyncOperationLogic. Also I need to skip unlock in ResourceLockAspect. To achieve this I will extend @ReleaseLock annotation to indicate another bean that will take care of releasing resources
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ResourceLock {
    Class<? extends IdentifierBuilder<?>> identifierBuilder();
    Class<? extends ResourceLocker> resourceLocker();
    String resourceLockerBeanName();
    String releaseResourceBeanName() default "";
}
and change ResourceLockAspect.execute method
    @Around("execution(* pl.mariusz.marciniak.operations.logic.OperationLogic.executeOperation(pl.mariusz.marciniak.operations.data.OperationData))"
           +" && @annotation(resourceLock)")
    private <T> Object execute(ProceedingJoinPoint pjp, ResourceLock resourceLock) throws Throwable {
        Object result = null;
        IdentifierBuilder<T> builder = resolveIdentifierBuilder(resourceLock);
        ResourceLocker locker = resolveResourceLocker(resourceLock);
        OperationData<T> operationData = (OperationData<T>) pjp.getArgs()[0];
        long[] objectsToLockIdentifiers = createIdentifiers(builder, operationData);// check if release resource bean is defined if yes initialize it
boolean releaseResourceDefined = resourceLock.releaseResourceBeanName().length()>0;
        initResourceReleaserOnAsyncOperationLogic(pjp.getTarget(), resourceLock.releaseResourceBeanName(), locker, objectsToLockIdentifiers);

        if (locker.lock(objectsToLockIdentifiers)) {
            try {
                result = pjp.proceed();
            } finally {
                if(!releaseResourceDefined) // release resource bean will take care of that
                    locker.unlock(objectsToLockIdentifiers);
            }
        } else {
            logger.info("Cannot perform operation " + operationData.getName() + ". Locked resources "
                            + new StrBuilder().appendWithSeparators(ArrayUtils.toObject(objectsToLockIdentifiers), ",").toString());
        }
        return result;
    }

    private void initResourceReleaserOnAsyncOperationLogic(Object target, String resourceReleaseBeanName, ResourceLocker locker, long[] objectsToLockIdentifiers) {
        AsyncOperationLogic<?> asyncOperationLogic = null;
        if (target instanceof AsyncOperationLogic<?>) {
            asyncOperationLogic = (AsyncOperationLogic<?>)target;
        } else if(target instanceof OperationExecutor<?>) {
            OperationExecutor<?> operationExecutor = (OperationExecutor<?>)target;
            if (operationExecutor.getOperationLogic() instanceof AsyncOperationLogic<?>) {
                asyncOperationLogic = (AsyncOperationLogic<?>)operationExecutor.getOperationLogic();
            }            
        }
        if(asyncOperationLogic != null) {
            ResourceReleaser releaser = appContext.getBean(ResourceReleaser.class);
            releaser.setResourceLocker(locker);
            releaser.setResourcesIdentifiers(objectsToLockIdentifiers);
            asyncOperationLogic.setResourceReleaser(releaser);
        }
    }
There are two changes comparing to prior version:
  • initResourceReleaserOnAsyncOperationLogic is added to initialize and set ResourceReleaser object
  • if resources releaser is defined the aspect doesn't unlock resources
Let's test this functionality by defining asynchronous logic:
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AsyncTransactionProcessingLogic implements AsyncOperationLogic<Transaction> {

    private Logger logger = LogManager.getLogger(AsyncTransactionProcessingLogic.class);

    @Autowired
    @Qualifier(value="transactionProcessingLogic")
    private OperationLogic<Transaction> logic;

    private ResourceReleaser releaser;

    @Async(value="singleOperationExecutor")
    public Future<Boolean> executeOperation(OperationData<Transaction> data) throws OperationFailedException {
        return logic.executeOperation(data);
    }

    public void operationFinished() {
        logger.debug("operation finished");
        releaser.unlock();
    }
    
    public void setResourceReleaser(ResourceReleaser releaser) {
        this.releaser = releaser;
    }

}

and executor which will lock resources
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class TransactionProcessingExecutor implements OperationExecutor<Transaction> {

    private OperationLogic<Transaction> logic;

    @ResourceLock(identifierBuilder = TransactionIdentifierBuilder.class, resourceLocker = TransactionLocker.class, resourceLockerBeanName = "transactionLocker")
    public Future<Boolean> executeOperation(OperationData<Transaction> data) throws OperationFailedException {
        return logic.executeOperation(data);
    }

    @Autowired
    @Qualifier(value = "transactionProcessingLogic")
    public void setOperationLogic(OperationLogic<Transaction> logic) {
        this.logic = logic;
    }

    public OperationLogic<Transaction> getOperationLogic() {
        return logic;
    }
}
Executing 3 operations (2 trying to lock transaction 203002322 and 1 transaction 125593085) using pool with only one thread can produce an output:
[main] INFO  pl.mariusz.marciniak.async.AsyncMainTest - starting asynchronous test with immediate lock
[main] DEBUG pl.mariusz.marciniak.locking.lockers.TransactionLocker - acquiring lock on [203002322]
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.operations.logic.impl.TransactionProcessingLogic - processing Sell operation on account number: 203002322
[main] DEBUG pl.mariusz.marciniak.locking.lockers.TransactionLocker - acquiring lock on [125593085]
[main] INFO  pl.mariusz.marciniak.locking.aop.ResourceLockAspect - Cannot perform operation complicated Buy operation on account. Locked resources 203002322
[main] INFO  pl.mariusz.marciniak.async.AsyncMainTest - executing other logic ...
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.operations.logic.impl.TransactionProcessingLogic - processing Sell operation on account number: 203002322
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.operations.logic.impl.TransactionProcessingLogic - processing Sell operation on account number: 203002322
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.operations.logic.impl.TransactionProcessingLogic - processing Sell operation on account number: 203002322
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.locking.aop.ReleaseResourcesAspect - releasing resources
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.operations.logic.impl.AsyncTransactionProcessingLogic - operation finished
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.locking.lockers.TransactionLocker - releasing lock on [203002322]
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.operations.logic.impl.TransactionProcessingLogic - processing Sell operation on account number: 125593085
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.operations.logic.impl.TransactionProcessingLogic - processing Sell operation on account number: 125593085
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.operations.logic.impl.TransactionProcessingLogic - processing Sell operation on account number: 125593085
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.operations.logic.impl.TransactionProcessingLogic - processing Sell operation on account number: 125593085
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.locking.aop.ReleaseResourcesAspect - releasing resources
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.operations.logic.impl.AsyncTransactionProcessingLogic - operation finished
[singleOperationExecutor-1] DEBUG pl.mariusz.marciniak.locking.lockers.TransactionLocker - releasing lock on [125593085]
Buy operation couldn't access locked resources, when it was invoked. So the functionality works as desired.

22 May, 2013

Operation Logic Executor - Implementation of locking mechanism

   In previous post, I proved that we can easily combine concepts of asynchronous execution and resource locking. Now I can implement locking mechanism. I will use simple idea of storing locked resources’ identifiers in set, but there are no limits to create more complex solutions. First of all @ResouceLock should be configurable and give user possibility to use any locking method. That is why I extended previous @ResourceLock annotation to:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ResourceLock {
    Class<? extends IdentifierBuilder<?>> identifierBuilder();
    Class<? extends ResourceLocker> resourceLocker();
    String resourceLockerBeanName();
}
I added resourceLocker and resourceLockerBeanName to fetch bean containing locking logic. User can also define identifierBuilder bean, which will create unique identifiers for resources. I didn’t add bean name for builder, because I don’t want programmers to customize builder logic, while for resourceLocker it can be useful (e.g. locker inserting blocked identifiers to tables, where programmer will only change query for the same type of bean).
public interface IdentifierBuilder<T> {
    long[] getIdentifiers(OperationData<T> operationLogicArgs);
}

I decided to return identifiers as an array of longs. It means that programmer needs to take care of mapping different type keys or complex keys to long values. I’m aware that such a limitation can be inconvenient and error-prone, but for purpose of this example I will leave it as it is.
public interface ResourceLocker {
    boolean lock(long... identifiers);
    boolean unlock(long... identifiers);
    boolean isLocked(long identifier);
}
Here also it will be much more better to throw exception than return boolean value, which doesn’t give any information what went wrong.
Before implementing interfaces, lets present resource class.
public class Transaction {
    private long   accountNumber;
    private String transactionType;

    public long getAccountNumber() {
        return accountNumber;
    }
    public void setAccountNumber(long accountNumber) {
        this.accountNumber = accountNumber;
    }
    public String getTransactionType() {
        return transactionType;
    }
    public void setTransactionType(String transactionType) {
        this.transactionType = transactionType;
    }
}
For objects of this type I define operation similar to one used for strings processing from prior post:
@Component
public class TransactionProcessingLogic implements OperationLogic<Transaction> {

    private Logger logger = LogManager.getLogger(TransactionProcessingLogic.class);

    @ResourceLock(
            identifierBuilder=TransactionIdentifierBuilder.class,
            resourceLocker=TransactionLocker.class,
            resourceLockerBeanName="transactionLocker"
    )
    @Async
    public Future<Boolean> executeOperation(OperationData<Transaction> data) throws OperationFailedException {
        boolean result = false;
        try {
            Object obj = data.getValueObject();
            if (obj instanceof Transaction) {
                Transaction transaction = (Transaction) obj;
                long startTime = System.currentTimeMillis();
                do {
                    logger.debug("processing " + transaction.getTransactionType() + " operation on account number: " + transaction.getAccountNumber());
                    Thread.sleep(500);
                } while (startTime + 10000 > System.currentTimeMillis());
                result = true;
            }
        } catch(InterruptedException e) {
            logger.error(e);
        }
        return new AsyncResult<Boolean>(result);
    }

}
Only transactions for different accounts can be operated simultaneously. So identifier builder can provide account number.
@Component
public class TransactionIdentifierBuilder implements IdentifierBuilder<Transaction> {
    public long[] getIdentifiers(OperationData<Transaction> operationData) {
        return new long[] {operationData.getValueObject().getAccountNumber()};
    }
}
Having identifiers I can implement ResourceLocker.
@Component
public class TransactionLocker implements ResourceLocker {

    private final Logger logger = LogManager.getLogger(TransactionLocker.class);

    private Set<Long>    lockedResources;

    @PostConstruct
    private void init() {
        lockedResources = new HashSet<Long>();
    }

    public boolean lock(long... identifiers) {
        Set<Long> resourcesIdentifiers = new HashSet<Long>();
        synchronized (lockedResources) {
            for (long identifier : identifiers) {
                if (lockedResources.contains(identifier)) {
                    return false;
                }
                resourcesIdentifiers.add(identifier);
            }
            logger.debug("acquiring lock on " + resourcesIdentifiers);
            lockedResources.addAll(resourcesIdentifiers);
        }
        return true;
    }

    public boolean unlock(long... identifiers) {
        Set<Long> resourcesIdentifiers = new HashSet<Long>();
        synchronized (lockedResources) {
            for (long identifier : identifiers) {
                if (lockedResources.contains(identifier)) {
                    resourcesIdentifiers.add(identifier);
                }
            }
            logger.debug("releasing lock on " + resourcesIdentifiers);
            lockedResources.removeAll(resourcesIdentifiers);
        }
        return true;
    }

    public boolean isLocked(long identifier) {
        return lockedResources.contains(identifier);
    }

}
As I previously wrote, this simple implementation bases on storing objects identifiers in set. I moved logging that was initially in aspect into this class. In fact there are many more changes in aspect code.
@Aspect
@Component
public class ResourceLockAspect {

    private Logger             logger = LogManager.getLogger(ResourceLockAspect.class);

    @Autowired
    private ApplicationContext appContext;

    @Around("execution(* pl.mariusz.marciniak.operations.logic.OperationLogic.executeOperation(pl.mariusz.marciniak.operations.data.OperationData))"
           +" && @annotation(pl.mariusz.marciniak.locking.annotations.ResourceLock)")
    private <T> Object execute(ProceedingJoinPoint pjp) throws Throwable {
        Object result = null;
        ResourceLock resourceLock = fetchAnnotationData(pjp);
        IdentifierBuilder<T> builder = resolveIdentifierBuilder(resourceLock);
        ResourceLocker locker = resolveResourceLocker(resourceLock);
        OperationData<T> operationData = (OperationData<T>) pjp.getArgs()[0];
        long[] objectsToLockIdentifiers = createIdentifiers(builder, operationData);
        if (locker.lock(objectsToLockIdentifiers)) {
            result = pjp.proceed();
            locker.unlock(objectsToLockIdentifiers);
        } else {
            logger.info("Cannot perform operation " + operationData.getName() + ". Locked resources "
                            + new StrBuilder().appendWithSeparators(ArrayUtils.toObject(objectsToLockIdentifiers), ",").toString());
        }
        return result;
    }

    private <T> long[] createIdentifiers(IdentifierBuilder<T> builder, OperationData<T> operationData) {
        return builder.getIdentifiers(operationData);
    }

    private <T> IdentifierBuilder<T> resolveIdentifierBuilder(ResourceLock annotation) {
        Class<? extends IdentifierBuilder<T>> identifierBuilder = (Class<? extends IdentifierBuilder<T>>) annotation.identifierBuilder();
        return appContext.getBean(identifierBuilder);
    }

    private ResourceLocker resolveResourceLocker(ResourceLock annotation) {
        Class<? extends ResourceLocker> resourceLockerClass = annotation.resourceLocker();
        String resourceLockerBeanName = annotation.resourceLockerBeanName();
        return appContext.getBean(resourceLockerBeanName, resourceLockerClass);
    }

    private ResourceLock fetchAnnotationData(ProceedingJoinPoint pjp) throws NoSuchMethodException {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        String methodName = signature.getMethod().getName();
        Class<?>[] parameterTypes = signature.getMethod().getParameterTypes();
        ResourceLock annotation = pjp.getTarget().getClass().getMethod(methodName, parameterTypes).getAnnotation(ResourceLock.class);
        return annotation;
    }
}

First of all I changed a pointcut of my aspect. Previously advice was executed for all methods annotated with @ResourceLock. Currently it is required that method must be named executeOperation, take pl.mariusz.marciniak.operations.data.OperationData parameter and belong to object implementing pl.mariusz.marciniak.operations.logic.OperationLogic. In line 14 I fetch annotation from method declaration and then use it to retrieve builder and locker beans. Using builder bean I can change objects stored in operationData argument into array of identifiers. These are passed to locking mechanism.
Methods for fetching beans and creating identifiers are straightforward, so I won’t describe them. More interesting is operation of annotation fetching. I get method name and parameters from join point and then find proper method, which provides also information about annotation. In fact there is a easier way to get annotation data of join point in Spring.
    @Around("execution(* pl.mariusz.marciniak.operations.logic.OperationLogic.executeOperation(pl.mariusz.marciniak.operations.data.OperationData))"
           +" && @annotation(resourceLock)")
    private <T> Object execute(ProceedingJoinPoint pjp, ResourceLock resourceLock) throws Throwable {

In this case annotation is added to method parameters and additionally pointcut definition is changed to point to this additional parameter @annotation(resourceLock).

Let’s check if locking mechanism works correctly. I used executor with pool size equal 5 and data:
    private void testAsyncTransaction() throws OperationFailedException {
        logger.info("starting asynchronous test");
        OperationLogic<Transaction> logic = appContext.getBean("transactionProcessingLogic",OperationLogic.class);
        OperationData<Transaction> sellTransactionDataForAccount1 = prepareOperationDataForTransaction(prepareTransaction(SELL_TRANSACTION, ACCOUNT_1));
        OperationData<Transaction> sellTransactionDataForAccount2 = prepareOperationDataForTransaction(prepareTransaction(SELL_TRANSACTION, ACCOUNT_2));
        OperationData<Transaction> buyTransactionDataForAccount1 = prepareOperationDataForTransaction(prepareTransaction(BUY_TRANSACTION, ACCOUNT_1));
        logic.executeOperation(sellTransactionDataForAccount1);
        logic.executeOperation(sellTransactionDataForAccount2);
        logic.executeOperation(buyTransactionDataForAccount1);
        logger.info("executing other logic ...");
    }

    private OperationData<Transaction> prepareOperationDataForTransaction(Transaction transaction) {
        OperationData<Transaction> transactionData = new TransactionData("complicated "+transaction.getTransactionType()+" operation on account");
        transactionData.setValueObject(transaction);
        return transactionData;
    }
    private Transaction prepareTransaction(String transactionType, long accountNumber) {
        Transaction transaction = new Transaction();
        transaction.setAccountNumber(accountNumber);
        transaction.setTransactionType(transactionType);
        return transaction;
    }

Possible output is:
22:36:29.954 [main] INFO  pl.mariusz.marciniak.async.AsyncMainTest - starting asynchronous test
22:36:29.960 [main] INFO  pl.mariusz.marciniak.async.AsyncMainTest - executing other logic ...
22:36:29.968 [operationExecutor-3] DEBUG pl.mariusz.marciniak.locking.lockers.TransactionLocker - acquiring lock on [203002322]
22:36:29.968 [operationExecutor-2] DEBUG pl.mariusz.marciniak.locking.lockers.TransactionLocker - acquiring lock on [125593085]
22:36:29.968 [operationExecutor-3] DEBUG pl.mariusz.marciniak.operations.logic.TransactionProcessingLogic - processing Buy operation on account number: 203002322
22:36:29.968 [operationExecutor-2] DEBUG pl.mariusz.marciniak.operations.logic.TransactionProcessingLogic - processing Sell operation on account number: 125593085
22:36:29.980 [operationExecutor-1] INFO  pl.mariusz.marciniak.locking.aop.ResourceLockAspect - Cannot perform operation complicated Sell operation on account. Locked resources 203002322
22:36:30.468 [operationExecutor-3] DEBUG pl.mariusz.marciniak.operations.logic.TransactionProcessingLogic - processing Buy operation on account number: 203002322
22:36:30.469 [operationExecutor-2] DEBUG pl.mariusz.marciniak.operations.logic.TransactionProcessingLogic - processing Sell operation on account number: 125593085
...
Sell operation at line 7 was blocked as expected.