ClassLoader.getResources(String)

Alan Bateman Alan.Bateman at oracle.com
Wed Mar 7 12:59:14 UTC 2018



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





More information about the jigsaw-dev mailing list