Optional framework dependencies: requires static vs automatic modules
jhoeller at pivotal.io
Fri Feb 3 18:14:52 UTC 2017
I've been experimenting with a Spring/Hibernate application on Jigsaw
again, in particular with respect to including module-info descriptors in
our framework jars... as opposed to using the framework jars as automatic
Unfortunately, it seems that "requires static" is transitive at compilation
time: Compiling an application module against a framework module which in
turn declares "requires static" some optional third-party module fails if
that optional third-party module is not on the application's compilation
module path, even if that module is not needed at all and won't be on the
application's runtime module path either.
As an example: "spring-context" has a couple of optional dependencies, e.g.
on Groovy and Kotlin. If it declares those as "requires static" in its
module-info, application modules compiling against it are currently forced
to have Groovy and Kotlin on their compilation module path. This case is
particularly odd since there will be hardly an application using both of
those languages at the same time.
The arrangement works fine at runtime in such a typical Spring stack, with
the optional modules not present and the JVM not complaining. However, the
effect that javac requires application builds to have all of Spring's
optional dependencies on the compilation path is clearly a showstopper: We
won't ever be able to ship module-info descriptors in our core framework
jars that way.
Note that we do not have that problem with automatic modules: Those can see
optional modules on the module path depending on availability, with the
framework reacting to their presence, even decoupled from the specific
module names (since we do not have to refer to them anywhere). It seems
that automatic modules are semantically a better fit for us for that
reason, even long term.
However, with automatic modules, we can't transitively expose *required*
dependencies: Application modules declaring "requires spring-context" have
to explicitly declare "requires spring-beans" and "requires spring-core"
etc since many of spring-context's exposed types refer to types from
spring-beans and spring-core. Nevertheless, this is the best that we can
offer at this point.
Was it intentional for "requires static" to work that way? Am I missing
something? From my perspective, "requires static" means that the referenced
module has to be present when compiling the declaring module... but not
when compiling other modules depending on the declaring module.
More information about the jigsaw-dev