Does #SuppressWarnings work with warnings generated by annotations? - java

Assume that I have an annotation that generates a warning. The annotation is on a method.
e.g.
#AnnotationThatGeneratesAWarning
public void doSomething() {
//stuff
}
Can I use #SuppressWarnings to suppress it? Does #SuppressWarnings work with warnings generated by annotations, or just on warnings generated by the method itself?

What IDE are you using? What's the code that generates the warning?. A good IDE will generally suggest the String to use in the #SuppressWarnings, but it's better to first try to fix the warning, if that's not possible and as a last resource use #SuppressWarnings.
EDIT :
You can tell that #SuppressWarnings won't work with other annotations looking at its documentation. As you can see:
#Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
The targets do not include ANNOTATION_TYPE, meaning that #SuppressWarnings can not be applied to other annotations.

I have tested the following in Eclipse. The annotations are from Spring MVC.
#SuppressWarnings("all")
#RequestMapping("/{foo}/somepage.do")
public void serveAPage() {
}
The {foo} in the #RequestMapping generates a warning as it's not being assigned to a variable*. The warning description is "URI template variable "foo" is not defined".
#SuppressWarnings("all") should suppress all warnings for the method. Eclipse still shows a warning, despite this.
As far as I can tell, you can't use #SuppressWarnings to suppress warnings caused by an annotation.
*This was the code that originally prompted the question. Fixing the code so it doesn't cause an exception is trivial and not the point of the question.

Related

In what order are Java constraints being executed

I have a Java method in which the method itself is annotated with a constraint (cross-parameter) and the arguments are also annotated with constraints (#NotNull, #NotEmpty etc).
Is the method constraint validated after method argument validation or is the order of validation not specified?
Annotations don't inherently do anything. They just mark things. javac itself knows what #Deprecated and #Override and #FunctionalInterface mean, but the effects are always to either do nothing, or to generate a compiler error: These annotations do not cause the compiler to generate any code.
Aside from Project Lombok this is a general principle of annotations, and even Project Lombok is an annotation processor: You have to put lombok on your classpath during a compilation, or nothing happens.
In other words, it is not possible for the #NonNull annotation in your code to generate any null check all on its own. The constraints are applied elsewhere, or by a code generating annotation processor that you explicitly include by putting it on the classpath or passing it along as annotation processor. For example, it IS possible for code you invoke to introspect your method and notice things. Thus, you could for example have:
class Example {
#NotEmpty String name;
}
and then you can do:
new Example("");
and this won't cause an exception. But you could do:
Validator validator = SomeHypotheticalValidationLibrary.newValidator();
validator.validate(new Example(""));
and then this validator would produce an error stating that the instance you provided fails verification. This is an example of annotations being introspected.
And now to answer your question:
The order in which such constraints are validated depends entirely on the validation library you use to do the validation; out of the box, the annotation itself does not and cannot produce any validation code. You'd have to check the documentation of your validation library, and provide the context within which you are validating.
If you're talking specifically about lombok's #NonNull - lombok scans your code for null checks (either of the form if (x == null) throw new Something(); or of the form Objects.nullCheck or guava's nullcheck). If it finds a nullcheck for an #NonNull annotated parameter, lombok does nothing. If it doesn't, it generates a nullcheck after all your explicit null checks. Lombok stops scanning for nullchecks once it hits a line that is NOT a nullcheck (so, neither an if (x == null) nor a methodInvocation(x, "optional text");). #NonNull is currently the only annotation that causes lombok to generate validation code (there is no #lombok.NotEmpty).
We may be able to give more insights if you explain which annotation processors / validation frameworks you are using.

tell Intellij that class is part of library, so it's normal that methods are unused

IntelliJ is giving me warnings when my methods are unused. Except that I am developing a library, so the methods are used in other projects but never in the current library.
I know I can tell IntelliJ to remove warning if I associate the methods with a specific annotation (That's what I do for reflective methods).
But is there a way to avoid adding annotation to stop the warnings?
Or at least to provide annotation only for the class, not for each method within the class?
It is quite simple to use #SuppressWarnings("ALL") annotation at the class level for suppressing the warnings.
#SuppressWarnings("ALL")
public interface UserService {
void f1();
void f2();
}
Second method is also fairly simple which will allow you to suppress warnings for whole IDE. Go and disable inspection for unused methods globally - in Preferences go to Editor > Inspections > Java > Declaration redundancy > Unused declaration and untick Methods.

#SuppressWarnings annotation on Application Level

I was reading this question, where #SuppressWarnings annotation is used on class level.
Suppose I have multiple classes in my application, so is there a way that I can use #SuppressWarnings on application level? As applying #SuppressWarnings on every class is redundant for me.
this is what javadoc says for #SupressWarnings
#Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
#Retention(value=SOURCE)
public #interface SuppressWarnings
#Target clearly mentions places where #SupressWarnings can be applied. So you can not apply at application level. Even doc go ahead and says
As a matter of style, programmers should always use this annotation on the most deeply nested element where it is effective. If you want to suppress a warning in a particular method, you should annotate that method rather than its class.
So its discouraged to do at parent level where it is not applicable.

Java Annotation Processing Tool #NoNull

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 {}
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)
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.
#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

Ignore Deprecated Type Warnings on import Statement

I'm importing a class which has been deprecated, which I'm forced to use.
I want to suppress the deprecated error using the #SuppressWarnings("deprecation") annotation.
As per the comment on that annotation:
As a matter of style, programmers should always use this annotation on
the most deeply nested element where it is effective. If you want to
suppress a warning in a particular method, you should annotate that
method rather than its class.
So I clearly don't want to annotate the class and thus suppress deprecation warnings on any type my class uses, but I also would like to use the import statement to avoid typing out the fully qualified type name, which spans my entire monitor, on each use of the deprecated class.
I think I want to do something like annotating the import statement with #SuppressWarnings (NOT POSSIBLE) or specifying in the #SuppressWarnings annotation which type to ignore warnings for (e.g. #SuppressWarnings("deprecation", "fully.qualified.type.name").
I want to indicate to the compiler "it's okay if I use this one, and only this one, deprecated class, referenced by its Simple Name, anywhere within this other class, and any other deprecated classes I reference you should let me know about".
Is there anything like this available?
A way to work around this would be to do the following, assuming you can extend the Deprecated class.
import comp.DeprecatedClass;
#SuppressWarnings("deprecation") public class MyDeprecatedClass extends DeprecatedClass{ }
Then you can use your version without having to worry about warnings.

Categories