JAVA Aspect Oriented Programming

ProceedingJoinPoint Java Tips & Tricks

The ProceedingJoinPoint.getSignature() method returns everything you need to get the actual class name, method name, return type and parameters for the joinpoint.

Java aspect programming is a powerful tool. In this post I will show you some quick tips & tricks related to the ProceedingJoinPoint Java class from the AspectJ framework. I will only cover a few simple things like: how to get class name information from ProceedingJoinPoint, method signature and even how to mock a ProceedingJoinPoint for use in unit tests. If you’re like me, you would appreciate having this info at hand.

Aspect Oriented Programming Terminology

Before we begin, let’s get some aspect oriented programming terms defined.

Aspect Oriented Programming Terminology

Joinpoint

A joinpoint is defined as a candidate point in the Program Execution of the application where an aspect can be plugged in. This point could be a method being called, an exception being thrown, or even a field being modified. These are the points where your aspect’s code can be inserted into the normal flow of your application to add new behavior.

Advice

This is an object which includes API invocations to the system wide concerns representing the action to perform at a joinpoint specified by a point.

Pointcut

A pointcut defines at what joinpoints, the associated Advice should be applied. Advice can be applied at any joinpoint supported by the AOP framework. Of course, you don’t want to apply all of your aspects at all of the possible joinpoints. Pointcuts allow you to specify where you want your advice to be applied. Often you specify these pointcuts using explicit class and method names or through regular expressions that define matching class and method name patterns. Some AOP frameworks allow you to create dynamic pointcuts that determine whether to apply advice based on runtime decisions, such as the value of method parameters.

ProceedingJoinPoint Get Class Name

Your pointcut definitions will likely match multiple places in the program execution flow. Inside your advice you will want to get information about where you are in the execution of the program. Let’s see for example how to get the actual class name of the joinpoint using the ProceedingJoinPointclass.

@Around("execution(public * com.example.services.*.*(..))")
 public Object myAdviceMethod(ProceedingJoinPoint pjp) throws Throwable {
  String actualClassName = pjp.getSignature().getDeclaringTypeName();
  System.out.println("Actual class name is: "+actualClassName);
  Object output = pjp.proceed();
  return output;
 }

This advice will be executed around all calls to public methods of classes from the com.example.services package. Calling pjp.getSignature().getDeclaringTypeName() will get the ProceedingJoinPoint class name and will return its fully qualified name (eg. com.example.services.UserService)

ProceedingJoinPoint Get Method Name

Sometimes you will need to perform some logic in your advice based on the name of the method called. Here’s how you use ProceedingJoinPoint to get the method name for your joinpoint.

@Around("execution(public * com.example.services.*.*(..))")
 public Object myAdviceMethod(ProceedingJoinPoint pjp) throws Throwable {
  String methodName = pjp.getSignature().getName();
  System.out.println("Actual method name is: "+methodName);
  Object output = pjp.proceed();
  return output;
 }

ProceedingJoinPoint Get Return Type

How about if you need the joinpoint return type?

Here’s the trick:

ProceedingJoinPoint.getSignature() returns a org.aspectj.lang.Signature. But, that’s just a top level interface. We can easily cast that to a more specific interface called org.aspectj.lang.reflect.MethodSignature. This interface will give us access to more goodies like for example the return type for our pointcut.

Here’ the example:

@Around("execution(public * com.example.services.*.*(..))")
 public Object myAdviceMethod(ProceedingJoinPoint pjp) throws Throwable {
  String returnTypeName = ((MethodSignature)pjp.getSignature()).getReturnType().getName();
  System.out.println("Method's return type is: "+returnTypeName);
  Object output = pjp.proceed();
  return output;
 }

 

ProceedingJoinPoint Get Parameter Names and Values

If for some reason, you need to get the joinpoint parameter names, you can use ((MethodSignature)ProceedingJoinPoint.getSignature()).getParameterNames(). This returns a String array with the names of the parameters passed to your joinpoint.

Most of the times you will want to retrieve the value of the arguments passed to the joinpoint. Simple call ProceedingJoinPoint.getArgs() to get the values of the parameters in an Object array.

Here’s how you do both:

@Around("execution(public * com.example.services.*.*(..))")
 public Object myAdviceMethod(ProceedingJoinPoint pjp) throws Throwable {
  String[] paramNames = ((MethodSignature)pjp.getSignature()).getParameterNames();
  Object[] paramValues = pjp.getArgs();
  Object output = pjp.proceed();
  return output;
 }

How to Mock ProceedingJoinPoint Signature

Test Driven Development (TDD) is almost a must in complex applications. But, if you have to test aspects it can get a bit difficult to implement.

You can mock the MethodSignature class, but I imagine you want to further mock that to return a Method class instance. Well, since Method is final, it cannot be extended, and therefore cannot be mocked. You should be able to create a bogus method in your test class to represent your ‘mocked’ method. I usually do it something like this:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;

import java.lang.reflect.Method;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class MyTest {
    UserService UserService;

    @Test
    public void testingAMethod() {
        userService = new UserService();

        ProceedingJoinPoint joinPoint = mock(ProceedingJoinPoint.class);
        MethodSignature signature = mock(MethodSignature.class);

        when(joinPoint.getTarget()).thenReturn(accountService);
        when(joinPoint.getSignature()).thenReturn(signature);
        when(signature.getMethod()).thenReturn(myMethod());
        //work with 'someMethod'...
    }

    public Method myMethod() {
        return getClass().getDeclaredMethod("someMethod");
    }

    public void someMethod() {
        //customize me to have these:
        //1. The parameters you want for your test
        //2. The return type you want for your test
        //3. The annotations you want for your test
    }
}

Want to Learn More About Java Aspect Oriented Programming with AspectJ?

If you are interested in a structured approach to learning Aspect Oriented Programming in Java using AspectJ I highly recommend this book AspectJ Cookbook: Aspect Oriented Solutions to Real-World Problems from Amazon.

Did You Find This Post Useful?

If yes, drop me a comment and let me know.

If no, drop me a comment and tell me what else regarding Aspect Oriented Programming and ProceedJoinPoint you would have liked to read.

John Negoita

View posts by John Negoita
I'm a Java programmer, been into programming since 1999 and having tons of fun with it.
[jetpack-related-posts]

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top