0

I want to create an annotation that restricts a developer from specifying null as a parameter, which has been annotated with @NoNull

For example, if I create this method:

public void printLine(@NoNull String line) {
    System.out.println(line);
}

On a method call, I want an error to appear if the user specifies null for line: printLine(null);

I have been using APT for only a little bit of time, and am wondering how to do this (if possible)?

This is the annotation I have created so far:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.SOURCE)
public @interface NoNull {}
Thomas Nappo
  • 241
  • 4
  • 13
  • Have you considered looking at other implementations? – Dave Newton Sep 04 '12 at 20:57
  • I have never seen an implementation of _@NoNull_. Do you mind linking them? – Thomas Nappo Sep 04 '12 at 20:58
  • 1
    There are plenty of `@NotNull`/`@NonNull` annotations, can't you use one of them ? http://stackoverflow.com/questions/4963300/which-notnull-java-annotation-should-i-use . Some of them are used by your IDE (IntelliJ for instance) to reports bug, I think that the last Eclipse too, there is findbugs also. – Alex Sep 04 '12 at 21:05
  • @Alex The point isn't to use the annotation only for readability, but to _enforce_ the annotation at compile-time with APT. – Thomas Nappo Sep 04 '12 at 21:06
  • Check out this SO thread http://stackoverflow.com/questions/8981540/enforcing-java-annotations-at-compile-time on writing an annotation processor. – RNJ Sep 04 '12 at 21:13
  • @RNJ, I have read tutorials on using APT, but I need help to specifically make an _@NoNull_ processor. – Thomas Nappo Sep 04 '12 at 21:15
  • You'd need to find every location where the method is called, track every parameter passed to the method, see if you can even *determine* if it's null or not, and take it from there. Good luck! – Dave Newton Sep 04 '12 at 21:16
  • I need to know how to search through method calls. Is there a way with APT or reflection... or some other library? – Thomas Nappo Sep 04 '12 at 21:17

3 Answers3

3

Compile time will be tough to check, since you're really dealing with runtime values. If you want to create annotations to automatically add code to check this stuff, you should look at project lombok:

http://projectlombok.org/

It uses an annotation processor to add code to your beans to do various things.

For example:

@Getter @Setter
private int id;

The annotation processor would automatically add get/set methods to your bean.

I don't think it has null checks, but you should be able to add this in and contribute it.

Another option is to use the validation jsr, though this requires you to explicitly validate at runtime, but you could accomplish this with proxies or AOP.

@NotNull @Min(1)
public void setId(Integer id)
Matt
  • 11,523
  • 2
  • 23
  • 33
2

The point isn't to use the annotation only for readability, but to enforce the annotation at compile-time with APT

Considering that null is a runtime artifact, I don't see how you will enforce a null check at "compile time."

Instead, you'll have to modify your classes, and apt is not the tool to do this, at least not by itself. It exists to extract information about annotated elements from source files. But to enforce your @Null restriction, you need to modify the running class.

One thing that you could do is use apt to extract information about annotated parameters, then use a tool like aspectj to modify those classes at runtime to check the parameter value.

But that's a topic that's way too broad for a single SO question.

parsifal
  • 582
  • 3
  • 4
  • I do not need to modify the classes at runtime. If I can iterate through all method calls (and access their parameter values), I can simply print an error message. – Thomas Nappo Sep 04 '12 at 21:34
  • 1
    @Thomas - and how will you determine that the variable being passed to a method is null or not? What if that variable is set based on data read from a file? – parsifal Sep 04 '12 at 21:37
  • If you're just trying to find if any method in the chain is has a different annotation, then you still need to examine the bytecode of all callers of the annotated method, to find how they set the arguments to the annotated method. – parsifal Sep 04 '12 at 21:38
  • something like this, I'd imagine. for (MethodCall call : methodCalls) { for (Parameter parameter : filter(call.getParameters(), annotatedWithNoNull) { if (parameter.getValue() == null) { processingEnv.getMessager().printMessage(Kind.ERROR, "Cannot pass null as this parameter); } } } – Thomas Nappo Sep 04 '12 at 21:39
  • You can't tell at compile time whether a variable is going to be null or not. You can tell if a method is being _explicitly_ called with null as an argument, but that really doesn't help anyone very much. – Louis Wasserman Sep 04 '12 at 21:41
0

@Nullable, @Nonnull are locating in package: javax.annotation

Checkout guava, its got some nice things are type safety: http://code.google.com/p/guava-libraries/wiki/GuavaExplained

Solubris
  • 3,603
  • 2
  • 22
  • 37