With PMD, if you want to ignore a specific warning, you can use // NOPMD to have that line be ignored.
Is there something similar for FindBugs?
The FindBugs initial approach involves XML configuration files aka filters. This is really less convenient than the PMD solution but FindBugs works on bytecode, not on the source code, so comments are obviously not an option. Example:
<Match>
<Class name="com.mycompany.Foo" />
<Method name="bar" />
<Bug pattern="DLS_DEAD_STORE_OF_CLASS_LITERAL" />
</Match>
However, to solve this issue, FindBugs later introduced another solution based on annotations (see SuppressFBWarnings) that you can use at the class or at the method level (more convenient than XML in my opinion). Example (maybe not the best one but, well, it's just an example):
#edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
value="HE_EQUALS_USE_HASHCODE",
justification="I know what I'm doing")
Note that since FindBugs 3.0.0 SuppressWarnings has been deprecated in favor of #SuppressFBWarnings because of the name clash with Java's SuppressWarnings.
As others Mentioned, you can use the #SuppressFBWarnings Annotation.
If you don't want or can't add another Dependency to your code, you can add the Annotation to your Code yourself, Findbugs dosn't care in which Package the Annotation is.
#Retention(RetentionPolicy.CLASS)
public #interface SuppressFBWarnings {
/**
* The set of FindBugs warnings that are to be suppressed in
* annotated element. The value can be a bug category, kind or pattern.
*
*/
String[] value() default {};
/**
* Optional documentation of the reason why the warning is suppressed
*/
String justification() default "";
}
Source: https://sourceforge.net/p/findbugs/feature-requests/298/#5e88
Here is a more complete example of an XML filter (the example above by itself will not work since it just shows a snippet and is missing the <FindBugsFilter> begin and end tags):
<FindBugsFilter>
<Match>
<Class name="com.mycompany.foo" />
<Method name="bar" />
<Bug pattern="NP_BOOLEAN_RETURN_NULL" />
</Match>
</FindBugsFilter>
If you are using the Android Studio FindBugs plugin, browse to your XML filter file using File->Other Settings->Default Settings->Other Settings->FindBugs-IDEA->Filter->Exclude filter files->Add.
Update Gradle
dependencies {
compile group: 'findbugs', name: 'findbugs', version: '1.0.0'
}
Locate the FindBugs Report
file:///Users/your_user/IdeaProjects/projectname/build/reports/findbugs/main.html
Find the specific message
Import the correct version of the annotation
import edu.umd.cs.findbugs.annotations.SuppressWarnings;
Add the annotation directly above the offending code
#SuppressWarnings("OUT_OF_RANGE_ARRAY_INDEX")
See here for more info: findbugs Spring Annotation
At the time of writing this (May 2018), FindBugs seems to have been replaced by SpotBugs. Using the SuppressFBWarnings annotation requires your code to be compiled with Java 8 or later and introduces a compile time dependency on spotbugs-annotations.jar.
Using a filter file to filter SpotBugs rules has no such issues. The documentation is here.
While other answers on here are valid, they're not a full recipe for solving this.
In the spirit of completeness:
You need to have the findbugs annotations in your pom file - they're only compile time, so you can use the provided scope:
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>findbugs-annotations</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
This allows the use of #SuppressFBWarnings there is another dependency which provides #SuppressWarnings. However, the above is clearer.
Then you add the annotation above your method:
E.g.
#SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE",
justification = "Scanning generated code of try-with-resources")
#Override
public String get() {
try (InputStream resourceStream = owningType.getClassLoader().getResourceAsStream(resourcePath);
BufferedReader reader = new BufferedReader(new InputStreamReader(resourceStream, UTF_8))) { ... }
This includes both the name of the bug and also a reason why you're disabling the scan for it.
Finally you need to re-run findbugs to clear the error.
I'm going to leave this one here: https://stackoverflow.com/a/14509697/1356953
Please note that this works with java.lang.SuppressWarningsso no need to use a separate annotation.
#SuppressWarnings on a field only suppresses findbugs warnings
reported for that field declaration, not every warning associated with
that field.
For example, this suppresses the "Field only ever set to null"
warning:
#SuppressWarnings("UWF_NULL_FIELD") String s = null; I think the best
you can do is isolate the code with the warning into the smallest
method you can, then suppress the warning on the whole method.
Related
Javadoc (via Maven) is giving me the following error in one my Java JAX-RS interface method signatures:
error: element value must be a constant expression
Here is my JAX-RS interface:
public interface FooResource {
#Consumes(APPLICATION_FORM_URLENCODED_UTF_8)
public void bar();
}
Javdoc gives the error for #Consumes. Here is the definition for APPLICATION_FORM_URLENCODED_UTF_8, which appears in MyAppConstants in the same project:
public static final String APPLICATION_FORM_URLENCODED_UTF_8 =
APPLICATION_FORM_URLENCODED + ";" + CHARSET_PARAMETER + "=UTF-8";
And here is the definition of APPLICATION_FORM_URLENCODED, which appears in javax.ws.rs.core.MediaType:
public final static String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded";
And here is the definition of CHARSET_PARAMETER, which also appears in javax.ws.rs.core.MediaType:
public static final String CHARSET_PARAMETER = "charset";
Now I ask you: what about APPLICATION_FORM_URLENCODED_UTF_8 is not constant at compile time?
The error message didn't say that I have to provide a literal. It said I had to provide a constant. So what about this is not a constant?
(I could almost swear that this worked at one time but suddenly stopped working.)
Update: Found cause, but still don't understand.
For some reason, merely including the swagger-maven-plugin in the POM will trigger this problem! My code doesn't change at all, but as soon as I add the following dependency, suddenly I get Javadoc warnings for my existing code!!!
<dependency>
<groupId>com.github.kongchen</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<version>3.1.5</version>
</dependency>
How can a single dependency make Javadoc work differently on a code file? What is swagger-maven-plugin doing?
My best guess is that this happens because swagger-maven-plugin transitively (via io.swagger:swagger-core:1.5.13) an old version of the JAX-RS specification in javax.ws.rs:jsr311-api:1.1.1. Note that the JAX-RS 2 artifact ID is javax.ws.rs-api, Maven doesn't realize that they are different versions of the same JAR, and pulls them both in as dependencies. I can only guess that javax.ws.rs:jsr311-api in fact does not use constants for the variables in question. In any case, when I threw out swagger-maven-plugin and pulled in io.swagger:swagger-annotations (which was all I needed in this project for documentation), the problem went away.
See https://github.com/kongchen/swagger-maven-plugin/issues/543.
I have a Kotlin Gradle project. I added Lombok as a dependency and also registered it with kapt
compileOnly("org.projectlombok:lombok:$lombokVersion")
kapt("org.projectlombok:lombok:$lombokVersion")
I would like to use the #Slf4j annotation for automatic logger generation. It works for Java classes but not for the Kotlin ones.
Is using Kotlin and Lombok together even possible as of now? If I annotate a Kotlin class with #Slf4j and use log inside it I get
Unresolved reference: log
Evidently no annotation processing is applied.
Lombok does not run on your source code, but on the AST. Anyway, it is an annotation processor that is run at compile-time by the Java compiler. The Kotlin compiler does not use these annotation processors. See also the answer https://stackoverflow.com/a/35530223/2621917 straight from the horse’s mouth.
You cannot use annotation #Slf4j, but manually create its object in the class required.
Refer https://www.reddit.com/r/Kotlin/comments/8gbiul/slf4j_loggers_in_3_ways/
If all you want to use Lombok for is #Slf4j, then I'd suggest using kotlin-logging instead: https://github.com/MicroUtils/kotlin-logging
It's a simple wrapper around slf4j, so instead of annotating your class with #Slf4j, you use:
// Place definition above class declaration to make field static
private val logger = KotlinLogging.logger {}
// ...
logger.debug { "A message only logged if debug is enabled. With $variable support." }
Lombok's builder annotation support has been added to kotlin 1.8 as of late December 2022.
You can learn how to configure the plugin here.
In Short, add
plugins {
id 'org.jetbrains.kotlin.plugin.lombok' version '1.8.0'
id 'io.freefair.lombok' version '5.3.0'
}
to your Groovy/Gradle files, and/or take a look at the sample project.
It's not supported and, by the looks of things, it isn't going to be.
from kotlin 1.7.20 with K2 compiler it is possible.
https://kotlinlang.org/docs/whatsnew1720.html#support-for-kotlin-k2-compiler-plugins
For logging the best I could do - because #Slf4j did not work - was like creating abstract log class like:
package org.example
import org.slf4j.LoggerFactory
import org.slf4j.Logger
abstract class Log {
val log: Logger = LoggerFactory.getLogger(this.javaClass)
}
and usage:
package org.example
class MyClass {
companion object : Log() {}
#Test
fun someFun() {
log.info("Logging info")
}
}
I can't see how it would work without additional support from the lombok team.
Lombok is based on annotation processing so it runs during compilation time and runs on your source code, so I guess it assumes Java's syntax.
The Issue
I'm having a problem with ProGuard 4.11 (An application that can optimize, shrink and obfuscate Java code), using the proguard-maven-plugin (github.com/wvengen/proguard-maven-plugin) (Although that shouldn't matter that much, since the error is occurring at runtime and the maven plugin just calls the binary with some arguments as far as I know).
I have an annotation class which is stuctured like this (nothing special):
#Retention(RetentionPolicy.RUNTIME) #Target(ElementType.FIELD)
public #interface SqlValueCache {
String value();
SqlValueCache.Type type() default Type.OBJECT_UPDATE; //Type is just an ordinary enum
}
I also have some fields annotated with that annotation, but I'm skipping the type() parameter because I want to use the default value:
#SqlValueCache("nickname")
protected SqlValueHolder<String> nick;
Now I want to process that annotation at runtime:
SqlValueCache annotation = field.getAnnotation(SqlValueCache.class); //Skipped the validation
annotation.value(); //Works fine, because specified
annotation.type(); //java.lang.annotation.IncompleteAnnotationException, *not* using the default
As stated in the comment above, I get an IncompleteAnnotationException, stating that my annotation declaration is missing the type() value. But that value should be implied by the default Type.OBJECT_UPDATE! So now I'm wondering, why is that happening?
Assumptions
I assume that the default thing is stored in some kind of attribute that I need to specify in -keepattributes, but I haven't been able to figure out if this is true or which one it is.
Reproduction
It does work just as intended when not using ProGuard.
I have also made sure that the problem is in fact the missing implied value - The code runs as intended when using ProGuard, but explicitly specifying the type(), like so:
#SqlValueCache(value = "nickname", type = Type.OBJECT_UPDATE)
protected SqlValueHolder<String> nick;
I am using this method as a temporary workaround, but this isn't the prettiest solution in my opinion. Also, as stated above, I still want to know why this error is happening.
Thanks in advance for reading and investigating my question! :)
Appendix/Meta
Yes, I did search the web for solutions and did also use the StackOverflow searchbox. Using the title of this question and various other search queries, I could only find questions complaining about no annotations being kept at all or asking to keep subclasses of classes annotated, etc. I also searched for the exception, but the only useful result was the JavaDoc (docs.oracle.com/javase/7/docs/api/java/lang/annotation/IncompleteAnnotationException.html) of the exception I am encountering.
I'm sorry about the links, but I apparently need 10 reputation to post more than two, although I really like linking stuff :/
Stacktrace
I have attached the Stacktrace I got in console (class names won't be useful at all in my opinion - I can attach them if really necessary; My classes are also loaded by a custom class loader, but I doubt that that makes any difference):
java.lang.ExceptionInInitializerError
at <class with annotated field>
(...)
Caused by: java.lang.annotation.IncompleteAnnotationException: io.github.xxyy.common.sql.builder.annotation.SqlValueCache missing element type
at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:72) ~[?:1.7.0_51]
at com.sun.proxy.$Proxy18.type(Unknown Source)
at <line accessing type() of SqlValueCache>
(...)
ProGuard config
Here's my ProGuard config, should that be of any help (That's the part I find relevant to this question - Full file here: pastebin.com/u6wt00cj):
-dontskipnonpubliclibraryclassmembers
-target 1.7
-dontshrink
-dontoptimize
-repackageclasses io.github.xxyy.obf.towerdefense.client
-keepattributes SourceFile,LineNumberTable,*Annotations*,LocalVariable*Table
-keep,allowobfuscation class ** {
<fields>;
<methods>;
}
-keep,allowshrinking class **.annotation** {
<fields>;
<methods>;
}
# Also keep - Enumerations. Keep the special static methods that are required in
# enumeration classes.
-keepclassmembers enum ** {
public static **[] values();
public static ** valueOf(java.lang.String);
}
You also need to keep the AnnotationDefault attribute:
-keepattributes AnnotationDefault
You can get the same effect by changing *Annotations* to *Annotation* in your current -keepattributes option, so the wildcards match AnnotationDefault.
When I run CheckStyle over my Java project it says Missing package-info.java file. for some classes, but not all of them. I can't really figure out why this message appears only sometimes. Furthermore my project runs perfectly fine without the package-info.java.
What does the package-info.java do? Do I really need it for my Java projects?
It is used to generate javadocs for a package.
/**
* Domain classes used to produce .....
* <p>
* These classes contain the ......
* </p>
*
* #since 1.0
* #author somebody
* #version 1.0
*/
package com.domain;
Will generate package info for com.domain package:
Example result: https://docs.oracle.com/javase/7/docs/api/java/awt/package-summary.html
Annotations
Another good reason to use package-info.java is to add default annotations for use by FindBugs. For instance, if you put this in your package-info file:
#DefaultAnnotation(NonNull.class)
package com.my.package;
then when findbugs runs on the code in that package, all methods and fields are assumed to be non-null unless you annotate them with #CheckForNull. This is much nicer and more foolproof than requiring developers to add #NonNull annotations to each method and field.
Not only some findbugs annotations, but a lot of java annotations in common libraries have the java.lang.annotation.ElementType.PACKAGE type as one of the possible values of their own java.lang.annotation.Target annotation, e.g.:
com.google.gwt.core.client.js.JsNamespace
com.querydsl.core.annotations.Config
com.sun.xml.bind.XmlAccessorFactory
groovy.transform.BaseScript
java.lang.Deprecated
javax.annotation.Generated
javax.xml.bind.annotation.XmlAccessorOrder
org.hibernate.annotations.TypeDef
net.sf.ehcache.pool.sizeof.annotations.IgnoreSizeOf
org.apache.hive.common.HiveVersionAnnotation
org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeAction
org.codehaus.commons.nullanalysis.NotNullByDefault
org.eclipse.persistence.oxm.annotations.XmlNameTransformer
org.glassfish.jersey.Beta
org.jgroups.annotations.Experimental
and much more.
This package-info.java file would be the file, where you can place such annotations (along with the javadoc).
A package-info.java file allows adding javadoc to document a whole package. See http://docs.oracle.com/javase/7/docs/api/java/applet/package-summary.html for example.
If you don't care about missing package documentation, then ignore the warning or disable the JavadocPackage check.
The package-info.java is a Java file that can be added to any Java source package. It is used to provide info at a "package" level as per its name.
It contains documentation and annotations used in the package.
javadoc example is already provided in the answer, the below part explains how it works incase of annotations.
For example, in the below file it is used to "substitute" the occurance of joda.time.DateTime with org.jadira.usertype.dateandtime.joda.PersistentDateTime
#TypeDefs({
#TypeDef(name = "PersistentDateTime", typeClass = PersistentDateTime.class, defaultForType=DateTime.class)})
package xyz.abc;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;
import org.jadira.usertype.dateandtime.joda.PersistentDateTime;
import org.joda.time.DateTime;
There are a number of annotations available with which can be used to perform different things at "package" level. It can be found at https://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/annotations/package-summary.html
I currently have an Enum, which has a constructor that can take null and contains with the following SuppressWarning annotation:
#SuppressWarnings("all")
public enum TheEnum {
...
AN_ENUM_VALUE(null),
...
...
private TheEnum(TheEnum ... args) {
if (args != null){
...
...
}
...
}
I'm currently using MyEclipse workbench 10.6, and it seems to pick up the annotation fine. During a compilation on a dev machine, however, I get warnings related to the 'TheEnum' class.
The strange this is that within the project, there are #SuppressWarnings("unchecked") all over the place, and the compiler manages to pick these up and ignore them just fine.
Because of legacy issues, we have to use JDK 1.5.0_17 to compile, but it looks like it should pick up the "all" suppression:
[root#xxx]:/opt/jdk1.5.0_17/bin# ./javac -X
...
-Xlint:{all,deprecation,unchecked,fallthrough,path,serial,finally,-deprecation,- unchecked,-fallthrough,-path,-serial,-finally}Enable or disable specific warnings
any suggestions as to where I should look to see why 'all' is being ignored?
Don't use it in the first place.
#SuppressWarnings("all")
says, you are doing something wrong. I would cancel a contract ASAP with any developer developing code like this. Warnings are there for a reason, and a blanket ignore says "I don't care if my code actually works" like nothing else. This is the total opposite to writing unit tests somewhat: blanket disabling the compiler checks.
Judging from http://docs.oracle.com/javase/6/docs/technotes/tools/solaris/javac.html#options "all" might be an eclipse extension. Sun/Oracle Java 6 compiler probably only supports the following values: unchecked, path, serial, finally, fallthrough and deprecation.