nats.java icon indicating copy to clipboard operation
nats.java copied to clipboard

Add nullability annotations

Open matthewadams opened this issue 1 year ago • 4 comments

Proposed change

Please annotate the API, including return types and parameters, with @javax.annotations.NonNull or @javax.annotations.Nullable as appropriate so that users of the API know what can and can't be null.

Use case

My use case is when using jnats from kotlin, but it applies to any user of jnats. For example, I discovered that io.nats.client.api.KeyValueEntry has a method

public byte[] getValue() {
  return value;
}

that allows for the returned byte[] to be null. Kotlin builds nullability into the type system for compile-time checking, and if Java APIs include these annotations, the kotlin compiler can inform the developer better about nullability.

Contribution

No response

matthewadams avatar Aug 22 '24 19:08 matthewadams

@matthewadams We are currently looking at how we can improve integration with Kotlin, and this will make the list.

scottf avatar Aug 22 '24 19:08 scottf

Have an example of using JetBrains' annotations here: https://github.com/nats-io/nats.java/commit/869012beff5de73eb0715b03f794cf4ec0068494

Tried out javax and jakarta annotations for @NotNull as well, but those didn't seem to be recognized.

Without the @NotNull annotation you need to technically handle the case where entry.operation == null, even if it's not possible to be image

Adding JetBrains' @NotNull solves that. image

Could be an option to use those.

MauriceVanVeen avatar Aug 23 '24 09:08 MauriceVanVeen

An alternative that works as well: org.checkerframework:checker-qual using @NonNull.

MauriceVanVeen avatar Aug 23 '24 10:08 MauriceVanVeen

Maybe this is also an option? https://jspecify.dev/

cbasener avatar Sep 04 '24 13:09 cbasener

I support @cbasener and would like to encourage you to migrate your project from JetBrains nullable annotations to JSpecify. https://jspecify.dev/

JSpecify is developed collaboratively by major players across the Java ecosystem, aiming to be the unified, open standard for nullness annotations: i.e. Google (Android, Error Prone, Guava), JetBrains (IDEA, Kotlin), OpenJDK team, Spring, Sonar, etc

Spring 7 (Nov. 2025) uses JSpecify and Uber NullAway for ultimate Null Safety https://spring.io/blog/2025/03/10/null-safety-in-spring-apps-with-jspecify-and-null-away

magicprinc avatar Jul 20 '25 20:07 magicprinc

https://github.com/nats-io/spring-nats/issues/62

magicprinc avatar Jul 20 '25 20:07 magicprinc

If JetBrains is involved, wouldn't it stand to reason that their library will adhere to any collaboration they are part of? Can you please point me to any official statements from JetBrains.

scottf avatar Jul 20 '25 21:07 scottf

It is unexpectedly hard to find such information in plain sight 🙏😱 I have seen "JetBrains is in JSpecify committee" in newsgroups, YouTube videos, etc. I use IDEA, and it definitely supports JSpecify...

For Kotlin see: https://github.com/JetBrains/kotlin/blob/master/third-party/java8-annotations/org/jspecify/annotations/Nullable.java

For Oracle/OpenJDK: https://mail.openjdk.org/pipermail/valhalla-spec-experts/2022-November/002209.html https://github.com/jspecify/jspecify/wiki/jspecify-faq OpenJDK is a member of our group, and if Java ever one day has null-aware types, the JSpecify standard will be the only reasonable starting point to base it on.

magicprinc avatar Jul 20 '25 22:07 magicprinc

https://jspecify.dev/about/ ^ JetBrains is listed as a member with support in both: Kotlin and IntelliJ IDEA 🤷‍♀️

The most important: Spring migrates to JSpecify and replaces its own annotations, so the whole Spring infrastructure will eventually migrate to JSpecify.

Lombok supports it :)

JUnit: https://github.com/junit-team/junit-framework/pull/4557

NullAway (see also article about Spring and NullAway): https://github.com/uber/NullAway

For actual migration, you could find useful: https://docs.openrewrite.org/recipes/java/jspecify/migratefromjetbrainsannotations

magicprinc avatar Jul 20 '25 23:07 magicprinc

I'm inclined to make the change, especially since it's basically a search and replace of the import. I don't have to do the effort to put a class wide annotation that covers all non-null. My concern is over semver and I just want to think out loud here. ? We would be changing a dependency. Annoying yes. Breaking? Well if it was when I removed the library with the CVE and used bouncy castle, I didn't care. ? Would we be changing any api? No. What was marked as null/not null before does not change. No signature's change. Intellij users won't have to do anything. Other ide's... I assume that they won't either.

scottf avatar Jul 21 '25 13:07 scottf

I don't have to do the effort to put a class wide annotation that covers all non-null.

It is a working solution 👍: then the code has unknown nullability (default behavior). Or you can annotate package(s), not individual classes

it's basically a search and replace of the import

Yes in 99% cases But there are corner cases like Map.@Nullable Entry 😅

I was a long-time user of jsr305 javax.annotation.Nullable, but after some time I find JSpecify type annotations more expressive

Like in List<@Nullable T> → List is not null, elements can be null

magicprinc avatar Jul 21 '25 14:07 magicprinc

Can you please point me to any official statements from JetBrains.

https://www.jetbrains.com/idea/whatsnew/#page__content-jspecify-support--a-major-step-toward-safer-code

🥳🚀

magicprinc avatar Aug 04 '25 20:08 magicprinc