You know java is looking for a properties file in a specific locale. You may be baffled why java keeps complaining it can't find a properties file that is right there. A few things to keep in mind when debugging this type of errors:
- These resource properties files are loaded by classloader, similar to java classes. So you need to include them in your runtime
classpath.
- These resources have fully-qualified-resource-name, similar to a fully-qualified-class-name, excerpt you can't import a resource into your java source file. Why? because its name takes the form of a string.
ResourceBundle.getBundle("config")
tells the classloader to load a resource named "config"
with default package (that is, no package). It does NOT mean a resource in the current package that has the referencing class.
ResourceBundle.getBundle("com.cheng.scrap.config")
tells the classloader to load a resource named "config"
with package "com.cheng.scrap."
Its fully-qualified-resource-name is"com.cheng.scrap.config"
For instance, you have a project like
C:/ws/netbeans5/scrap>| build.xml+---build| /---classes| /---com| /---cheng| /---scrap| Scrap.class|+---src| /---com| /---cheng| /---scrap| config.properties| Scrap.java
For this statement in Scrap.java: ResourceBundle config = ResourceBundle.getBundle("config");
to work, you will need to cp src/com/cheng/scrap/config.properties build/classes/
such that config.properties
is directly
under classes
, and at the same level as com
. Alternatively, you can put config.properties
into aconfig.jar
such that config.properties
is at the root of config.jar
without any subdirectories,
and includeconfig.jar
in the classpath.
For this statement in Scrap.java: ResourceBundle config = ResourceBundle.getBundle("com.cheng.scrap.config");
to work, you will need to cp src/com/cheng/scrap/config.properties build/classes/
com/cheng/scrap/
such
that config.properties
is directly under classes
/
com/cheng/scrap/
, and at the same level as scrap
. Alternatively, you can putcom/cheng/scrap/
config.properties
(along
with the long subdirectories) into a config.jar
, and includeconfig.jar
in the classpath.
You may be wondering why it is made so confusing? The benefits are two-fold, as I see it:
- Location transparency. At runtime, config.properties is NOT a file, it's just a a loadable resource. config.properites may not exist in your project at all, and the person who wrote Scrap.java may have never seen this resource. A URLClassLoader can find
it in a network path or URL at runtime. This is especially important for server-side components such as EJB, Servlet, JSP, etc, who are normally not allowed to access file systems. When you ask classloaders for a resource, its physical location becomes irrelevant.
- Namespace mechanism. Having a package allows multiple packages to have resources with the same short name without causing conflicts. This is no different from java packages and xml namespaces.
再做翻譯。問題已經解決。主要是在寫自己的resource bundle的時候,如果是在定製開源架構的Messages(如jmesa或者ec),必須明確的是resource是用classloader在運行時讀入的,也就是不是在讀檔案,不能將.properties檔案放在某個檔案夾中,然後在web.xml中param-value寫檔案夾路徑。應該是寫class路徑,而且不能有.properties尾碼。web配置要細心啊,param-value寫檔案夾路徑的時候不能忘記前面的forward slash(前斜杠),而classPath則不需要這個。