Overriding requirements of 3rd party modules

Gunnar Morling gunnar at hibernate.org
Wed May 4 09:24:35 UTC 2016


Note that this is not a requirement specific only to JPA.

There are more cases where reusable components obtain a package from module
A at their own build time (and thus would declare requirements in
module-info.java accordingly) but need to work with the same package
provided by another module B when being part of a downstream application.

For instance there is the "stripped" javaee-api-7.0.jar which can be used
for compiling a module against the complete Java EE API (and thus seems
reasonable as requirement in module-info.java). But this JAR contains no
actual method implementations at all, instead the same packages must be
provided from other sources when executing a module compiled against it as
part of a downstream application.

Or consider the case of logging (abstractions). Suppose a library depends
on Commons Logging (JCL). An application using the library might wish to
work with slf4j though for a unified logging experience. For that purpose
slf4j provides a JCL-over-slf4j bridge. This is a drop-in replacement for
JCL, re-implementing the JCL packages but using slf4j and its configured
backend underneath. In such scenario the application developer would need
to override the requirement of the lib to JCL with the slf4j-based bridge.

I agree that in theory it'd be nice if there was a canonical source for
each package which then uses the service loader to bootstrap specific
implementations. But in practice we are not there. There may be several
providers of the same package (as in the case of JPA), or a package doesn't
foresee different implementations and thus should be replaceable with a
compatible alternative (the logging bridge example).

Thus it's my believe that it is vital for the module system to provide
application developers with means of overriding module requirements of
their dependencies with (package-compatible) alternatives.




2016-05-04 10:20 GMT+02:00 Emmanuel Bernard <emmanuel at hibernate.org>:

> On Tue 2016-05-03 14:45, Alan Bateman wrote:
> > On 03/05/2016 13:46, Gunnar Morling wrote:
> > > Hi,
> > >
> > > While looking into Jigsaw-enabling some existing code, I came across
> the
> > > following use case for which I'm seeking advice on how to deal with.
> > >
> > > Consider a 3rd party library that contains JPA entities. Application
> > > developers will include that library into their app and work with its
> > > entities as part of their model. The library author doesn't know which
> JPA
> > > provider will be used (Hibernate, EclipseLink etc.), so the library
> should
> > > work with any compatible provider.
> > >
> > > Now the different providers all have their own JPA API Jar. Thus in the
> > > module-info.java of the library, there'd be a "requires" clause to one
> of
> > > the API Jars (e.g. "hibernate-jpa-2.1-api") for compiling and testing
> the
> > > library.
> > >
> > > But users of the lib might want to use *another* JPA provider and hence
> > >   API Jar for their app. What's Jigsaw's approach for letting the user
> deal
> > > with that? I.e. how could the user override the requirement of the lib
> in
> > > order to work with the provider of their choice?
> > >
> > > I vaguely remember a concept of "module aliases" in earlier drafts
> which
> > > might have been used for that (for instance, all the different API Jars
> > > could act as "jpa-2.1"), but I cannot seem to find that in the current
> docs
> > > anymore.
> > >
> > The early exploration phase did have some support for aliasing (`provides
> > jpa` for example). This is not in the current design.
> >
> > An alternative is to use services of course, say where there is one API
> > module and a service provider interface to allow the implementation be
> > plugged in. The current design (with `uses` and `provides`) leads itself
> > very well to this type of loose coupling. We have many examples in Java
> SE
> > and the JDK. Sorry I don't know JPA too well to know whether this
> applies or
> > not but I do see a javax.persistence.spi package that looks like it
> > supporting plugging in alterative implementations.
>
> JPA uses the service loader pattern to find the list of implementations.
> But what Gunnar is describing is a concern of the API module itself.
>
> For reasons related to history, license, copyright openness concerns and
> code maintenance, there are several alternative incarnations of JSR APIs
> floating around. They are all sig compliant as per the TCK but they have
> different Maven GAVs
>
> For JPA at the very least, there is the Oracle and Red Hat version. I'm
> pretty sure Apache has its own too. So if the third party module Gunnar
> mentions does use the hibernate version (which its own name), there is
> no way for the third party module user to override this decision and use
> the Oracle one.
>
> Hope that clarifies.
>
> emmanuel
>


More information about the jigsaw-dev mailing list