4

I currently use

@DefaultAnnotation(NonNull.class)
package jobs;

import edu.umd.cs.findbugs.annotations.DefaultAnnotation;
import edu.umd.cs.findbugs.annotations.NonNull;

however the annotation @edu.umd.cs.findbugs.annotations.DefaultAnnotation is deprecated: http://findbugs.sourceforge.net/api/edu/umd/cs/findbugs/annotations/DefaultAnnotation.html

They propose to use javax.annotation.ParametersAreNonnullByDefault However, DefaultAnnotation not only targets parameters, but also fields and methods.

So, what is the javax.annotation alternative for setting fields and methods to Nonnull by default?

David Harkness
  • 35,992
  • 10
  • 112
  • 134
David Portabella
  • 12,390
  • 27
  • 101
  • 182

2 Answers2

4

As far as I know there is none. Wanting the same thing, I copied the source for ParametersAreNonnullByDefault into my own FieldsAreNonnullByDefault and MethodsAreNonnullByDefault and changed the @TypeQualifierDefault values to match (FIELD and METHOD respective). FindBugs picks up these new annotations perfectly.

Here's a sample for FieldsAreNonnullByDefault:

package com.sample;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import javax.annotation.meta.TypeQualifierDefault;

/**
 * This annotation can be applied to a package or class to indicate that the 
 * classes' fields in that element are nonnull by default unless there is
 * <ul>
 *   <li>an explicit nullness annotation
 *   <li>a default field annotation applied to a more tightly nested element.
 * </ul>
 */
@Documented
@Nonnull
@TypeQualifierDefault(ElementType.FIELD)  // <-- METHOD for return values
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldsAreNonnullByDefault {
}
David Harkness
  • 35,992
  • 10
  • 112
  • 134
1

So from the pure code point of view, there is not really any major difference.

The difference occurs once you start distributing your code afterwards.

As long as you do not ship your code with the annotations jar and a JRE, you should be OK.

If you are distributing a JRE then as you already know you need to comply with the Oracle Java Binary License.

You may want to refresh yourself with the terms of that license, specifically:

F. JAVA TECHNOLOGY RESTRICTIONS. You may not create, modify, or change the behavior of, or authorize your licensees to create, modify, or change the behavior of, classes, interfaces, or subpackages that are in any way identified as "java", "javax", "sun", “oracle” or similar convention as specified by Oracle in any naming convention designation.

So if you are distributing a JRE and the same distribution includes a jar file that defines classes in a javax subpackage, unless the classes comply with a specification released and published by a JSR, you are not complying with the terms of the Oracle Java Binary License.

It is at this point that you then should take a look at the JSR 305 official page.

At this point in time that JSR has not published anything:

JSR - as of March 2016 - is listed as dormant

So you will need to ensure that you do not distribute the "jsr305.jar" file beside a JRE in your Windows installer, OS-X installer, Docker image, etc.

Stephen Connolly
  • 13,872
  • 6
  • 41
  • 63
  • IIUC This only applies to the Oracle JRE and not the OpenJDK JRE. The official Java docker images typically use the OpenJDK – csanchez Nov 24 '16 at 10:06
  • This screenshot doesn't look complete. There is a specification published at that page, and the jsr305.jar complies with that specification. – Christopher Nov 24 '16 at 17:42
  • @Christopher can you please share the screenshot of the specification you refer to as having been published? The draft specification calls out for `@NonNull` and the jsr350.jar does not include such an annotation, rather including a `@Nonnull` annotation instead... I wish it were otherwise... I really do... but sadly I cannot see anything to counter – Stephen Connolly Nov 28 '16 at 10:13
  • @csanchez yep, OpenJDK is GPLv2 / GPLv2+Classpath and thus doesn't have the same issue as Oracle JRE for redistribution... but I think if you want to *say* you have included Java™ in your docker image that there is another TM usage agreement that will pull the same restrictions back on you... so just don't say the docker image includes Java... it can include a JRE or OpenJDK... but not Java! – Stephen Connolly Nov 28 '16 at 10:18
  • @StephenConnolly I'm not a lawyer, but I don't think case-sensitive differences between the draft specification and the reference implementation are substantively different in terms of creative content, for the purposes of copyright / licensing. The draft specification you linked above describes generically "nullness annotations", and only offers the case sensitive `@NonNull` as an example (with "e.g."). The reference implementation, originally published on code.google.com, is now available at https://github.com/amaembo/jsr-305/tree/master/ri – Christopher Nov 29 '16 at 19:40
  • @Christopher But case sensitivity in terms of a Java API is substantive. Just try compiling against an API that has changed the case of one annotation. – Stephen Connolly Dec 01 '16 at 13:20
  • @StephenConnolly I don't disagree that it is substantive to compatibility. I just think it's not substantive with respect to the copyright/license. In any case, the specification describes the annotation independent of the case-sensitivity of the implementation, and thus the implementation still matches the specification of the JSR, which is all that's necessary for it to match the exception for bundling in the Oracle Java Binary License technology restrictions section. – Christopher Dec 02 '16 at 00:06