5/20/2006

Debug java util MissingResourceException

java.util.MissingResourceException Can't find bundle for base name, locale...How did I get this exception? The crux of this problem is the requested resource, in most cases, a properties file, is not configured correctly in the classpath. For example, you have a properties file, connection.properties, in the same source directory as Java source files. Javac will compile *.java into *.class in a target directory such as build/classes, which is in your runtime classpath. But connection.properties is not copied into build/classes directory unless you either add a <copy> task after <javac> in the Ant build file, or do so manually.

How to fix it? Make sure this resource is configured correctly in the classpath through one of the following:

  • Like I said above, copy the resource from source directory to build/classes directory, which is in the classpath.
    • If your code is like ResourceBundle.getBundle("connection"), then after copying you should have build/classes/connection.properties.
    • If your code is like ResourceBundle.getBundle("com.javahowto.test.connection"), then after copying you should have build/classes/com/javahowto/test/connection.properties.
  • Or you can choose package resources into a jar file, say, connection-info.jar, which is included in runtime classpath (not needed in Javac classpath).
    • If your code is like ResourceBundle.getBundle("connection"), then connection-info.jar should contain this entry: connection.properties.
    • If your code is like ResourceBundle.getBundle("com.javahowto.test.connection"), then connection-info.jar should contain this entry: com/javahowto/test/connection.properties.
  • Or you can choose to put the resource in a separate resources directory, include resources directory in runtime classpath. This way you don't have to duplicate the resource in multiple directories/jar. The disadvantage is it's a little inconvenient at development time to have resource in a separate directory than Java code.
    • If your code is like ResourceBundle.getBundle("connection"), then you should have resources/connection.properties.
    • If your code is like ResourceBundle.getBundle("com.javahowto.test.connection"), then you should have resources/com/javahowto/test/connection.properties.

tags: , , ,

12 comments:

Brian Duff said...

ResourceBundle.getBundle() is really intended to look up translatable resources. In the example you give (connections.properties), it sounds like you're using it as a general mechanism for loading properties files from the classpath.

Although that works, it's relatively inefficent (it first tries to find locale specific versions of the properties file, which incurs a classloading overhead, and then must create a PropertiesResourceBundle instance for your properties file). If you're loading a nontranslated file, you can achieve the same effect using something like:


URL resUrl = myclass.getResource( "/org/acme/connection.properties" );
Properties props = new Properties();
properties.load( resUrl.openStream() );

howto said...

Brian, thanks for the comments. I agree ResourceBundle should be used for i18n purpose. But I also found it's often used (misused) for general properties-loading. Maybe I should change the example connection.properties to messages_en.properties.

I guess you mean myclass.getClassLoader().getResource();

Nevertheless, the same techniques still apply, since ClassLoader.getResource() works the same as ResourceBundle.getBundle();

Using ResourceBundle.getBundle() gives you an option to localize your properties in the future. For instance, I may want to use localized properties such as database.name, user.name, db.password, etc.

Ayisha said...
This comment has been removed by a blog administrator.
plush said...
This comment has been removed by a blog administrator.
photo soft said...
This comment has been removed by a blog administrator.
Anonymous said...

Thank you very much!! I dont know why no one clearly describes the solution like you have done. Excellent!

Jose Francisco said...

It was really useful, thanks a lot, I have always faced the same problem and i didnt know what was it about

Anonymous said...

I agree with all that have been said. A straight-forward explanation that you cannot find even in educational stuff. Thank you so much it saved me days and days of work.

Anonymous said...

Thanks for posting this clear explanation.

I stumbled on this error while trying to define a spring ResourceBundleViewResolver, thinking my properties had to be located in the /WEB-INF directory.

Your post helped me see the light :)

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

Thanks a lot... Even I was facing the same issue was trying to fix it for a whole day. Thanks a lot for your post.

Anonymous said...

Good explanation of an all to common error. Unfortunately I've found installs where adding the .prop to the under classes does note solve the problem IF the prop file is referenced in a code lib referenced in the classpath of the web project.

For instance, a servlet is using some custom logging lib (log.jar). It's referenced by the project. The logging methods are visible to the servlet and everything compiles. Assuming the log.jar needs values in the .prop file, it fails to find it when exercised IF the resource is located outside of the jar. Thus defeating the purpose of externalizing the jar to your particular web app instance. There are workarounds, but none are really satisfying.