On 31/01/2024 07:47, Piotr P. Karwasz wrote:
Hello,

The `requires` instruction can have two qualifiers `static` and
`transitive` that separately make perfect sense. For a module `foo`:

  * `requires static bar;`, makes resolution of the `bar` module
optional at runtime,
  * `requires transitive bar;`, allows each module that reads `foo` to
also read `bar`. As far as I understand this means that `bar` must be
present at both compile time and runtime.

There is however a third option allowed:

```java
module foo {
     requires static transitive bar;
}
```
It may be surprising but they do work together. If bar is resolved then foo will read bar. If there is another module baz that requires foo (and doesn't explicitly require bar) then baz will read foo, and if bar is resolved, then baz will read bar.


:
We often end up with such directives, when using the
`bnd-maven-plugin`, which maps the OSGi `resolution:=optional`
directive to `static` and the `uses:=...` directive to `transitive`.
If we mark a package as optional, but the package uses public types
from `bar`, we end up with `static transitive`.

Is this a bug of the plugin or does `static transitive` have a meaning?

I think it's more of a case that it is fragile for modules like foo to have bar types foo API signatures.  `requires static` is okay for things like annotations with a retention policy of "source" but going beyond that means giving up a bit on reliable configuration. In the example, foo probably has a reflection guard and is careful in their use of bar types. However, foo's user if baz and the maintainers of baz are unaware of these shenanigans. This creates a risk that baz code will get a CNFE at runtime.

-Alan

Reply via email to