Spring's need for optional dependencies
jhoeller at pivotal.io
Thu Dec 17 09:35:48 UTC 2015
Juergen from the Spring team here. Quick intro: Spring Framework project
lead since 2003, currently focusing on the Spring Framework 4.3 / 5.0
strategy for 2016-2017.
After extensive conversations with Mark and Alan at Devoxx Belgium in
November, I'd like to summarize our need for optional dependencies from
Our module arrangement in the Spring Framework project has been pretty
stable for about 10 years, splitting the core framework into ~20 modules
with a maximum size of ~1 MB each (some are much smaller). The module split
is largely based on domain (e.g. aop, beans, jdbc, messaging, orm, web,
webmvc, websocket), with each of those modules bringing in a few required
dependencies but in particular also optional dependencies which only apply
when certain third-party frameworks are used in combination with Spring.
Such external frameworks are up for the user to choose; Spring just reacts
to their presence and auto-configures itself for integration with those
frameworks. For example, when Jackson is present, we automatically register
message converters for it; when Joda-Time is present, we automatically
register type converters for its value types. This auto-configuration
experience is long-established in the Spring world, not only for
third-party libraries but also for the JDK: currently between 6, 7 and 8,
for example registering java.time converters automatically when JDK 8 is
present (along the lines of our Joda-Time support).
We have had tight OSGi alignment a few years back, with the framework
modules shipping bundle manifests out of the box. We backed out of this
again since it turned out to be a pain to maintain on our side, in
particular due to the inclusion of version ranges but also due to the
extensive length of the resulting manifests in our jar files. There are
still variants of the Spring modules which include OSGi metadata but they
are maintained by the Virgo project at Eclipse. The canonical Spring
Framework jars from Maven Central come without any such metadata at present.
Now, as of Spring Framework 5, we aim for being the best possible citizens
in a Jigsaw world (while retaining compatibility with JDK 8 at the same
time). Our roadmap is closely aligned with JDK 9 there, and we've got a
first milestone scheduled for June 2016 now. However, there is a
showstopper with Jigsaw: We cannot express the above-mentioned optional
dependencies at this point. Note that Spring's auto-configuration
experience just implies optionality at runtime; those dependencies are in
fact required at compile-time. We'd just like to let our framework modules
bootstrap even when none of those optional dependencies are present,
dealing with the resulting ClassNotFoundExceptions ourselves (we're simply
checking for the presence of certain classes and derive auto-configuration
decisions on that basis). This has been working pretty well for us for 10+
years, and we really need this to keep working when declaring our framework
modules with Jigsaw-compliant module-info files. After all, we'd love to
ship explicit metadata, not keep relying on classpath-like deployment where
such implicit access to other modules remains available.
The alternative would be decomposing the framework into finer-grained
modules which isolate each such dependency into its own module. Aside from
bumping up the number of core framework modules from ~20 to >50 that way,
we'd also lose most of our auto-configuration experience. Making the user
declare such integration modules explicitly is exactly what we're trying to
avoid: Instead, declaring a specific Spring module and a specific
third-party module should be all that it takes, e.g. spring-webmvc and
jackson-databind but no extra spring-webmvc-jackson.
So in summary, we have a strong need for some kind of optional marker in
Jigsaw dependency declarations, similar to optional resolution in OSGi.
Runtime optionality is all that it takes for our purposes: no different
treatment at compile time needed, just lenient bootstrapping which lets us
run into ClassNotFoundExceptions and deal with those. I imagine other
frameworks will be in a similar situation.
It'd be my pleasure to discuss our requirements in more detail if needed...
More information about the jigsaw-dev