Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pluggable resource loaders #2

Open
glassfishrobot opened this issue Jun 14, 2011 · 17 comments
Open

Pluggable resource loaders #2

glassfishrobot opened this issue Jun 14, 2011 · 17 comments
Assignees
Labels
Enhancement New feature or request

Comments

@glassfishrobot
Copy link

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.)

  • New method addResourceLoader(ResourceLoader resourceLoader) in javax.servlet.ServletContext which will register a ResourceLoader for use in the servlet context.

  • New web.xml / web-fragment.xml syntax:

   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

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
Reported by eirbjor

@glassfishrobot
Copy link
Author

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
eirbjor said:
I now have a working implementation of this based on Glassfish trunk.

I'll upload a patch, but I need to review the code and do some more testing first.

For now, here's a summary of changes/additions made:


M deployment/schemas/src/main/resources/glassfish/lib/schemas/javaee_6.xsd
M deployment/schemas/src/main/resources/glassfish/lib/schemas/web-common_3_0.xsd

Added support for new XML syntax com.example..

(I know these will need to be moved to the 3.1 / jeee7 versions of these files, but I decided not to do that now after a few failed attempts.


A + deployment/dol/src/main/java/com/sun/enterprise/deployment/node/web/ResourceLoaderNode.java
M deployment/dol/src/main/java/com/sun/enterprise/deployment/node/web/WebCommonNode.java
M deployment/dol/src/main/java/com/sun/enterprise/deployment/node/DescriptorFactory.java
A + deployment/dol/src/main/java/com/sun/enterprise/deployment/AppResourceLoaderDescriptorImpl.java
A + deployment/dol/src/main/java/com/sun/enterprise/deployment/web/AppResourceLoaderDescriptor.java
M deployment/dol/src/main/java/com/sun/enterprise/deployment/WebBundleDescriptor.java
M deployment/dol/src/main/java/com/sun/enterprise/deployment/xml/WebTagNames.java

Changes related to parsing the new and nodes and representing them as an AppResourceLoaderDescriptor. I pretty much stole the code from since they're structurally the same.


M web/javax.servlet/src/main/java/javax/servlet/ServletContext.java
A web/javax.servlet/src/main/java/javax/servlet/ResourceLoader.java

Added the ResourceLoader interface and ServletContext.addResourceLoader.


M web/web-core/src/main/java/org/apache/catalina/core/StandardContext.java
M web/web-core/src/main/java/org/apache/catalina/core/ApplicationContext.java
M web/web-core/src/main/java/org/apache/catalina/core/ApplicationContextFacade.java
M web/web-core/src/main/java/org/apache/catalina/servlets/DefaultServlet.java
M web/web-core/src/main/java/org/apache/catalina/Context.java
M web/web-core/src/main/resources/org/apache/catalina/core/LocalStrings.properties

  • Added support for adding resource loaders, programmatically or from a class name given via XML
  • Consult resource loaders when looking up resources in ServletContext's getResource*, getRealPath methods.
  • Consult resource loaders when serving resources in DefaultServlet.serveResource

M web/web-glue/src/main/java/com/sun/enterprise/web/TomcatDeploymentConfig.java

Register the context's resource loaders by using the information available in AppResourceLoaderDescriptor

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
eirbjor said:
When adding support for resource loaders to DefaultServlet, I found the serveResource method to be hard to work with.

I've filed an issue in the Glassfish Jira for this, with some suggestions for improvements:

http://java.net/jira/browse/GLASSFISH-16871

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
File: SERVLET_SPEC_2-2011-12-11.patch
Attached By: eirbjor

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
eirbjor said:
Patch includes API changes to the Servlet spec and a working Glassfish implementation of the changes

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
eirbjor said:
Demo web application project. The webapp tests that the container implements resourceloader according to the specification.

The project also includes a demo of hot deployment of JSPs from OSGi bundles.

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
eirbjor said:
Including post to user list for reference:

Thinking about it, my resource loader proposal for Servlet 3.1 might
have a multi-tenancy story as well as a dynamic deployment story.

I initially focused on a single tenant being able to dynamically
(hot)deploy resources. However, being able to define custom resource
loaders will also enable resource sharing across multiple tenants
without having to use container specific hacks or custom builds of
webapps.

I've uploaded a patch to the Jira issue which adds the ResourceLoader
interface and the ServletContext.addResourceLoader method. The patch
also includes a working implementation of resource loader support in
Glassfish trunk.

Finally, I've also uploaded a proof-of-concept web application. This
application tests the container's implementation of the ResourceLoader
API. And just for fun, I threw in a ResourceLoader backed by OSGi
bundles using Apache Felix.

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
eirbjor said:
Updated poc with improved tests and getResourcePaths() implementation for OSGi

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
File: resourceloader-poc-2011-12-15.zip
Attached By: eirbjor

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
eirbjor said:
Patch implementing ResourceLoader support for Jetty 8

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
File: SERVLET_SPEC_2_JETTY_8_2011-12-15.patch
Attached By: eirbjor

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
File: SERVLET_SPEC_2_JETTY_servlet-spec_2011-12-15.patch
Attached By: eirbjor

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
eirbjor said:
Updates to Jetty's 3.0 Servlet Spec module adding ResourceLoader

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
This issue was imported from java.net JIRA SERVLET_SPEC-2

@glassfishrobot
Copy link
Author

@manorrock
Copy link

@gregw I would favor for the deployment model to stick to WAR file or WAR file exploded in a directory to be the 2 ways that have to be supported. Any other really should be left up to the vendor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants