In my program, a ResourceBundle is used for localized console output messages. The resource bundle is loaded from properties files, and currently, there is only the default locale with English messages. It is package-wise located at klfr.sof.SOFMessages (i.e. file src/klfr/sof/SOFMessages.properties). This resource bundle can without a problem be located and loaded with a single line like:
ResourceBundle.getBundle("klfr.sof.SOFMessages");
For most purposes and most of my project, I just used this bundle directly and it never posed a problem. Locales seem to work normally, too.
However, for expanding the localization to logging, I want to attach the resource bundle to the java.util.logging system. Then, I could use message keys in my log calls, etc. For this purpose, I use this code:
ResourceBundle R = ResourceBundle.getBundle("klfr.sof.SOFMessages");
Logger.getLogger("").setResourceBundle(R);
But this throws the following error:
Exception in thread "main" java.lang.IllegalArgumentException: resource bundle must have a name
at java.logging/java.util.logging.Logger.setResourceBundle(Logger.java:2320)
at <line with setResourceBundle()>
This seemed very weird to me. The "name" that the exception mentions is the base name of the resource bundle, as retrieved by getBaseBundleName(). The JavaDoc states:
Returns the base name of this bundle, if known, or null if unknown. If not null, then this is the value of the baseName parameter that was passed to the ResourceBundle.getBundle(...) method when the resource bundle was loaded.
As I stated, I did use getBundle to load this resource bundle successfully. I did provide a base name. And the base name is now gone. I called getBaseBundleName() myself after loading the RB and it is null.
Because I could not believe this, I dug into the Java source code that loads PropertyResourceBundles, including debugging the above lines and stepping deep into the library call stack, and tracking the bundle objects that were created. I found out that the name attribute, returned by getBaseBundleName(), isn't ever set by any code that runs in my case (Properties file, small parent chains, module class loader, and similar defaults).
So what am I doing wrong? Is there something wrong with my code or Java itself? The java --version states:
openjdk 14.0.1 2020-04-14
OpenJDK Runtime Environment (build 14.0.1+7)
OpenJDK 64-Bit Server VM (build 14.0.1+7, mixed mode, sharing)
Just a side note: The root logger seems to be the logger with empty string name (not the getGlobal() thing). It works for the "root" purpose in all other things like log handlers, logging levels etc., so I never questioned it.