Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

URLs: Smart resource identifiers

Keep resource names and resource loading strategies separate

  • Print
  • Feedback

QWhat convenient pluggability patterns exist for loading resources via custom URLs?

A In the previous Java Q&A article, "Smartly Load Your Properties," you observed how loading resources via classloaders can help decouple application logic from the details of the application's disk location. Although that article put some emphasis on loading .properties definitions, the real message was how it was done: by loading them through the classpath. As long as you can load a piece of data via an InputStream, you can also do it via ClassLoader.getResourceAsStream(), which hides the disk location details behind the classloader façade.

In this follow-up article, I take the next step towards disk location-independent code nirvana. Just like in the previous article, everything will be possible with a very simple augmentation of the existing Java APIs: sometimes the real Java skill is not in writing yet another library but rather in knowing how to use the existing core Java functionality to its full potential.

Think of URLs as smart resource names



In "Smartly Load Your Properties," I showed a simple method for loading resources via classloaders. The end result was that you could use a simple Java string as a resource identifier. For modest goals, that was good enough.

However, resource loading through classloaders can have disadvantages too. If the underlying storage changes (e.g., you add a new file to a directory in the classpath), is a classloader supposed to notice that or must it cache its view of the classpath at the time the classloader is instantiated? Some of them do, but most don't. This behavior is left ambiguous in the Java specifications. And even looking back at PropertyLoader.loadProperties() in my previous Java Q&A post, the caching behavior will depend on the LOAD_AS_RESOURCE_BUNDLE boolean flag.

Loading resources via files, resource bundles, or classloader resource streams are all different resource loading strategies with varying behavioral aspects. Using just a string for a resource name isn't really enough because it says little about the loading strategy—that knowledge must be maintained implicitly in your code.

It makes sense to augment a plain String resource identifier with some self-descriptive metadata that details how the resource is handled. Furthermore, it's even better to convert such an identifier to a Java object that knows how to retrieve its own content.

Java already has something that fits the bill quite well: java.net.URLs. Forgetting about HTTP and the Web for a moment, you can think of a URL as a string in a simple format:

    <protocol> ":" <protocol-specific/opaque-part>


The protocol prefix is the metadata that explains how to process the rest of the URL, which could be almost an arbitrary string (e.g., a resource identifier and other collateral information). And methods like URL.openStream() and URL.getContent() retrieve the content behind the name.

A filename will always be just a filename, and a classloader resource name will always be just that. But a URL can be both of those and much more. Let's see how to take advantage of it.

  • Print
  • Feedback

Resources