usr-local-ΕΨΗΕΛΩΝ
usr-local-ΕΨΗΕΛΩΝ

Reputation: 26904

getParameterAnnotations returning empty array

I'm implementing an AOP-based validation mechanism for method arguments. When I specify @NotNull annotation to a method argument I make sure that it's not null or throw exception.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface NotNull
{

}

Target Spring bean annotated method

@Override
    public PagedCollection<Result> findByRange(@NotNull BigInteger start, @NotNull BigInteger end)
    {
        if (start.compareTo(end) > 0)
            throw new IllegalArgumentException("a > b"); // I haven't yet created an annotation for that

        ...
    }

Aspect code

@Before("execution(public * myapp.managers.spring.*.*(..))")
public void before(JoinPoint jp) throws Throwable
{
    MethodSignature signature = (MethodSignature) jp.getSignature();
    Method method = signature.getMethod();

    before(method, jp.getArgs(), jp.getTarget());
}

public void before(Method method, Object[] args, Object target)
        throws Throwable
{
    Annotation[][] methodAnnotations = method.getParameterAnnotations();

    if (args != null)
    {
        for (int i = 0; i < args.length; i++)
        {
            for (Annotation annotation : methodAnnotations[i])
            {
                if (annotation.annotationType() == NotNull.class)
                    if (args[i] == null)
                        throw new IllegalArgumentException(...);
            }

        }

    }
}

I tried to invoke findByRange with a null argument and debugging. Debug shows that the joinpoint is activated, but method.getParameterAnnotations() returns an empty array for each parameter, like parameters are not annotated.

How to fix?

Upvotes: 3

Views: 1412

Answers (1)

usr-local-ΕΨΗΕΛΩΝ
usr-local-ΕΨΗΕΛΩΝ

Reputation: 26904

Working solution found

Since I have used the manager-implementation design patter (as you can see my bean method is annotated @Override) I found that the way to let the @NotNull annotation work is to annotate the parameter on the interface, and not in the concrete implementation

public interface {
    public PagedCollection<Result> findByRange(@NotNull BigInteger start, @NotNull BigInteger end);
}


public class MyServiceImpl implements MyService
    @Override
    public PagedCollection<Result> findByRange(BigInteger start, BigInteger end)
    {
        if (start.compareTo(end) > 0)
            throw new IllegalArgumentException("a > b"); // I haven't yet created an annotation for that

        ...
    }
}

Upvotes: 3

Related Questions