wiki:UsingResources

Using resources in Java

Resources are data files that are needed by some application, and that are more or less static. (So normal input files are not reources) Think of icons, images, configuration files, etcetera. The main problem with resources is to store them in a place where the application can find them, in particular when it is not running on the system of the developer of the application, including webstart or jar-based deployment. So, using absolute file paths like: C:\myjavaapps\projectXYZ\data\config.xml, referring to some absolute directory on your hard disk is a bad idea. Relative pathes like ../data/config.xml are somewhat better, since you can relocate your project as a whole, including the data. But it still cannot handle web or jar deployment. A better solution is to place resource data in some place that can be found by Java method like “getResourceAsStream”. Such methods search for resource directories on the Java classpath. In particular, when an application runs from a jar file, that jar file is (automatically) on the classpath. This leads to the following solution:

  • A project must have a resource (sub)directory, alongside subdirectories like src, etcetera.
  • The resource directory is automatically on the class path when running the project’s applications.
  • When releasing the project (using e.g. ant nbuild, ant release), the contents of the resource directory will be packaged within the project’s jar file, together with the class files.
  • Resource files should be read exclusively via methods like getResourceAsStream.

The hmi.util package includes a few helper classes for applying this pattern.

Use cases

Put resource file like “config.xml” in your project’s resource director, and create a hmi.util.Resource object in your application like so:

Resources res = new Resources("");

Read your config file directly to a String

String configText = res.read("config.xml");

Open a Java Reader for the config file

BufferedReader configReader = res.getReader("config.xml");

Open an inputstream for the config file

BufferedInputStream ips = res.getInputStream("config.xml");

hmi.util.Resources

The Resources class is used for more easily loading resources from some resource directory. To make this more clear, you should understand how the Java methods like getResourceAsStream search for resource files:

  • First, you have a number of directories that are present on the Java runtime classpath. For instance, our ant build files ensure that (by default) the project’s resource subdirectory is always on the classpath. A second ant property called resource.path, which is usually set in the build.properties file when necessary, includes more directories on the runtime classpath. For example, a line like: resource.path=\${shared.repository}/Humanoids will include the Humanoids directory from the HMI shared repository on the classpath.
  • The directories on the runtime classpath do not usually contain resource files themselves; rather, one defines subdirectories where the real resource reside. This is often necessary to avoid confusion: if some file like “config.xml” occurs at several places, that happen to be all on the classpath, it becomes unclear which one will actually be used.
  • Therefore, the preferred method is to create a separate hmi.util.Resources object for every single resource directory by specifying the local directory name within one of the classpath directories. Of course, that directory name should not occur twice within the classpath directories. For example, with the resource directory and the \${shared.repository}/Humanoids on the classpath we might have a local resource directories called “icons” and “shaders” within the project’s resource directory, and resource directories like “armandia/dae” and “armandia/shaders” within ${shared.repository}/Humanoids. For each of these four directories, we then define a Resource object, for example:
    Resources icons = new Resources("icons"); //referring to the project’s resource/icons directory.
    Resources projectshaders = new Resources("shaders"); //referring to the project’s resource/shaders directory.
    Resources model = new Resources("armandia/dae"); //referring to the armandia/dae directory within the ${shared.repository}/Humanoids/directory.
    

Resource caching: hmi.util.ResourcePool

The hmi.util.!Resource class is fine for loading resources from a resource directory, but does not take care of resource caching. That is, when you load, for instance, some texture image via a Resource object, you might easily load the same texture image several times. Even worse, you might create several different GLTexture objects, all based on the same texture image, resulting in wasting texture memory space of your graphics card. The ResourcePool class has been designed to handle such situations. A ResourcePool object requires you to create a so called “ResourceLoader” object, to be used when some resource has to be actually loaded from a resource file. The ResourcePool will then cache the result, and deliver the cached object the next time that the same resource is asked for.

Outdated: resource setup in Elckerlyc

Elckerlyc depends on a large number of resources, such as the graphical embodiments of avatars, the collections of gestures and face expressions, etcetera. There are basically two ways to include these resources into your project. Note that if a specific resource is included in more than one way at the same time, the system will get confused about which version to use :)

1) Include resources as released library packages.

When you don't need to modify resources, this is a very good way to incorporate the main resources in your project. In HmiDemo/MyFirstProject you will see a good example of how to do this.

  • for most resource sets, a release library exists (usually somewhere in HmiShared/repository/resource/HMI)
  • you specify the inclusion of one of these libraries by adding an entry to the ivy.xml file of your project
  • in command prompt, do "ant resolve" to actually import the libraries specified in ivy.xml
  • more information on the release library versioning and import system, see the global project guides in HmiShared/docs

2) Include the resources by directly adding to the classpath a reference to the source versions of these resources.

When you want to modify some of the the resource files, this is a good option. Note that if you change core resource files, they may be overwritten by new versions.

  • source versions of most resources reside in the HmiResource repository
  • add them to the class path by adding a "resource.path=..." setting to the build.properties file
  • see HmiDemo/MyAlphaProject for an example of this method
  • there are a few pre-specified paths expressions:

${shared.repository} refers to the Shared repository directory ${shared.resources} refers to the HmiResource? repository directory

3) Final note: any resource file that you put below the 'resource' directory of your own project, will automatically be available through its relative path from this 'resource' directory. See the extended documentation on using resource paths for more information.

User contributions

Ask specific questions below...

Discussion

UsingResources
 unsolved

Add your experiences and comments below...