Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add run-time processing of @NotNull annotation

I was quite surprised to see that IntelliJ actually does runtime verification of @NotNull within IDEA when running/debugging a unit test. Is it possible for me to add this same feature to my maven build? (What jars/jvm settings do I require?)

like image 860
krosenvold Avatar asked Aug 10 '11 09:08

krosenvold


2 Answers

IDEA is using its own method of instrumenting bytecode to add such validations. For command line builds we provide javac2 Ant task that does the instrumentation (extends standard javac task). If you generate Ant build from IDEA, you will have an option to use javac2.

We don't provide similar Maven plug-in yet, but there is third-party version which may work for you (though, it seems to be a bit old).

like image 53
CrazyCoder Avatar answered Sep 28 '22 12:09

CrazyCoder


I'd go the AOP way:

First of all you need a javax.validation compatible validator (Hibernate Validator is the reference implementation).

Now create an aspectj aspect that has a Validator instance and checks all method parameters for validation errors. Here is a quick version to get you started:

public aspect ValidationAspect {

    private final Validator validator;

    {
        final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();

    }

    pointcut serviceMethod() : execution(public * com.yourcompany**.*(..));

    before() : serviceMethod(){
        final Method method = (Method) thisJoinPoint.getTarget();
        for(final Object arg : thisJoinPoint.getArgs()){
            if(arg!=null) validateArg(arg,method);
        }
    }

    private void validateArg(final Object arg, final Method method) {
        final Set<ConstraintViolation<Object>> validationErrors = validator.validate(arg);
        if(!validationErrors.isEmpty()){
            final StringBuilder sb = new StringBuilder();
            sb.append("Validation Errors in method ").append(method).append(":\n");
            for (final ConstraintViolation<Object> constraintViolation : validationErrors) {
                sb.append(" - ").append(constraintViolation.getMessage()).append("\n");
            }
            throw new RuntimeException(sb.toString());
        }
    }

}

Use the aspectj-maven-plugin to weave that aspect into your test and / or production code.

If you only want this functionality for testing, you might put the aspectj-plugin execution in a profile.

like image 43
Sean Patrick Floyd Avatar answered Sep 28 '22 11:09

Sean Patrick Floyd