While the pluggability support in Servlet 3.0 was a great improvement, I do still find it to be a somewhat limited. In 3.0, all resources have to be bundled inside META-INF/resources in a jar in WEB-INF/lib in the deployed war. I think this is a bit rigid and that we would benefit from adding more flexibility in how resources can be loaded.
I suggest adding a provider interface to the servlet API which will allow implementors to load resources from arbitrary locations. That could be the file system, the network, OSGi bundles, the classpath, some generated in-memory representation or any other source which can locate and load resources.
How would this be useful? Our particular use case is to support plugin based architectures on the Servlet/JSP platform. For these kinds of applications, it it desirable to distribute apps and plugins independently. It is inconvenient having to reassemble the application war file just to add or upgrade a plugin. It should be possible to add it simply by dropping it in a folder. In the same way, would like to add and remove plugins at runtime. Both of these requirements are impossible to implement with Servlet 3.0, but should be easy to implement with the proposed API.
Other use cases that comes to mind might be: sharing of resources across contexts, loading resources from source during development and being able to separate downloadable application data from the application itself.
Also note that the current Servlet 3.0 way of loading resources from /META-INF/resources on the classpath could be implemented as a resource loader in the suggested design. Likewise, the normal resource loading from the war file could also be modeled as a resource loader. So in a way, we already have multiple ways of loading resources, we just don't have a well defined name and concept around it that people can use. (Or rather framework developers, I don't see this as something the average developer will commonly have to deal with directly, they'll probably use a framework/library which supports it)
For the purpose of discussion, I'll throw out an initial design idea here:
- New interface ResourceLoader:
package javax.servlet.ResourceLoader;
interface ResourceLoader {
URL getResource(String path);
Set getResourcePaths(String path);
InputStream getResourceAsStream(String path);
}
(The methods will behave similar to their cousins in javax.servlet.ServletContext, just being scoped to a single ResourceLoader. "path" is the path being looked up.)
com.example.MyResourceLoader
- Change javax.servlet.ServletContext methods getResource, getResourcePaths and getResourceAsStream to consider registered resource loaders in addition to the resources found in the war and in META-INF/resources. Resource loaders would be consulted in the order of their registration.
I'm very interested in hearing objections, ideas for alternative/improved/simpler designs, security concerns or other considerations. There's probably no shortage of things I haven't thought about