On 07/03/2018 12:11, Stephen Colebourne wrote:
Following up on this, it does feel like the use case is now simply not
possible. I have a similar problem with
ClassLoader.getResources(String) in threeten-extra.

https://github.com/ThreeTen/threetenbp-extra/blob/master/src/main/java/org/threeten/extra/scale/SystemUTCRules.java#L202

The ThreeTen-Extra project defines a config file
org/threeten/extra/scale/LeapSecond.txt. The code uses
ClassLoader.getResources(String) to find the latest version of the
file, which may be in the threeten-extra jar file, or in any jar file
that uses threeten-extra.jar. ie. to replace the version from
threeten-extra.jar, a user simply has to add a file with the same
name/package to their jar file.

threeten-extra.jar contains org/threeten/extra/scale/LeapSecond.txt
application.jar also contains org/threeten/extra/scale/LeapSecond.txt

Under JPMS this fails, as the resource cannot be located in
org/threeten/extra/scale in a different jar file. But this appears
makes the whole design impossible to make work with JPMS.

The code in threeten-extra.jar cannot possibly know about the package
names of the application.jar, so there is no way for it to find the
config file.

There seem to be only two solutions to this
- ServiceLoader, but that is for code, not config files
- forcing the application to manually register their config file

Both of these provide a markedly worse outcome.

Am I missing something?

Resources can't be both encapsulated and not encapsulated at the same time. If a module has a resource in a package that is intended to be located by code in other modules using ClassLoader getResourceXXX then it has to open the package.

In the above, then I assume the main issue isn't resource encapsulation, it's that you've got two modules on the application module class containing the same package so they can't both be mapped to the application class loader.

You've dismissed services but I would expect it to provide a nice solution. The service interface might be very simple, something like:

public interface LeapSecondDataProvider {
    LeapSecondData data();
}

or better still, define methods that allow SystemUTCRules select the right version of the leap second data. Applications that ship their own leap data second would ship an implementation of this class. Yes, it's different to searching the class file for configuration files but a lot more reliable.

-Alan



Reply via email to