JetBrains' @NotNull works only when project built from IDEA

1.7k views Asked by At

I wrote a simple project to learn how to work with annotation validation. For that puspose I added maven dependency (also I tried javax.validation, that does not work for me):

<dependency>
    <groupId>org.jetbrains</groupId>
    <artifactId>annotations</artifactId>
    <version>15.0</version>
</dependency> 

and used it this way:

public boolean add(@NotNull T entry){ ...

When I build the project from IDEA, everything is fine, but it does not work when compiling the code with maven command. In decompiled class file I noticed that IDEA compiles my classes in different way. It adds this check:

if (entry == null) {
    $$$reportNull$$$0(0);
}

And maven does not.

I'm I doing something wrong? Please, tell me how it should be used (no matter jetbrains or javax validation).

4

There are 4 answers

0
GhostCat On

Partially guessing here: you see, it is not "IDEA" that puts that extra check into the byte code.

The thing is: annotations can also be used to generate code (see here for some further reading). And as you can see from that link; the core thing for code generation is: that annotation requires a javax.annotation.processing.Processor class. And that will be used by the compiler to turn the source code annotation into something reasonable within byte code.

If I get you right, you failed to get those javax parts setup for your maven compile. So probably the one part is missing there; so the solution is to fix your maven setup to provide all required dependencies.

0
Jakub Ch. On

Your @NotNull annotation seems to be part of IntelliLang plugin, designed to support coding in IDEA (i.e. helps in contract coding). I doubt it is available outside of IDEA.

Before you start working with language injections, make sure that the IntelliLang plugin is enabled. The plugin is bundled with IntelliJ IDEA and is activated by default

I don't know much about it, so please say hello to reference

javax.validation on the other hand is designed to quite different things. It checks if data object content is valid via Bean Validation from java EE

0
Martin del Necesario On

As noted by other answers, Intellij implemented a process to add the null checks to your code before it is compiled. There is one unofficial maven plugin (https://github.com/osundblad/intellij-annotations-instrumenter-maven-plugin) and some forks of it, but it is not longer maintained (last change was over a year ago) and I couldn't get it to work.

Thus, I recommend using another annotation instead. In my project, I switched to Lombok instead, which also has some nice additional features. To get it to work, you explicitly need to tell Lombok to throw another exception. See this working example:

Prequisites:

You need to add the lombok dependency to your maven pom.xml (find the latest version here):

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

In your root directory (inside the folder, that contains 'src') create a lombok.config with the following content:

lombok.nonNull.exceptionType=IllegalArgumentException

1. Use case

Now you can use the @NonNull annotation for parameters and the null-checks will be generated automatically. You probably also need to add the maven-surefire-plugin to your pom.xml.

2. Use case

There is a neat possibility to let Lombok figure out itself, when the null check is necessary and when not for constructors. The following code will generate a constructor with to parameters (list1, list2). But it will only throw an IllegalArgmentException/NullPointerException, if the argument 'list1' is null, because list2 is not annotated with @NonNull.

import lombok.RequiredArgsConstructor;
import java.util.List;

@RequiredArgsConstructor
public class A {

    @NonNull
    private final List<String> list1;

    private final List<String> list2;
    
    ...
}
0
seanf On

A Maven plug-in was created to do the same thing for Maven builds:

https://github.com/osundblad/intellij-annotations-instrumenter-maven-plugin

It only works with JetBrains annotations by default.