How to load JSF / facelets library from a common d

2019-07-25 03:38发布

问题:

This question already has an answer here:

  • Obtaining Facelets templates/files from an external filesystem or database 1 answer

We have a number of webapps that all use a certain JSF library. We'd like to place the library in a common location or on the main classpath. The trouble is that the system expects the library to be in WEB-INF/lib so the webapp classloader can scan it and load it.

We are the creators of this particular library, and during development it's way easier to have it on the main classpath.

Is this possible? Can anyone give an example of what to put in web.xml to make this happen (if that's the right mechanism)?

回答1:

We are the creators of this particular library, and during development it's way easier to have it on the main classpath. Is this possible?

For Facelets resources this is possible with a custom ResourceResolver in webapp itself.

public class FaceletsResourceResolver extends ResourceResolver {

    private ResourceResolver parent;
    private String basePath;

    public FaceletsResourceResolver(ResourceResolver parent) {
        this.parent = parent;
        this.basePath = "META-INF/resources"; // TODO: Make configureable?
    }

    @Override
    public URL resolveUrl(String path) {
        URL url = parent.resolveUrl(path); // Resolves from WAR which would also do META-INF/resources of JARs in WAR.

        if (url == null) {
            url = getClass().getResource("/" + basePath + path); // Resolves from JARs in WAR when base path is not META-INF/resources.
        }

        if (url == null) {
            url = Thread.currentThread().getContextClassLoader().getResource(basePath + path); // Resolves also from anywhere else in classpath.
        }

        return url;
    }

}

To get it to run, configure it as follows in webapp's web.xml:

<context-param>
    <param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
    <param-value>com.example.FaceletsResourceResolver</param-value>
</context-param>

For annotated JSF artifacts like managed beans, etc which needs to be scanned by the JSF annotation scanner, this is not possible. The JAR has really to end up in /WEB-INF/lib. See also How to reference JSF managed beans which are provided in a JAR file?



回答2:

You can try the shared folder mechanism provided with the web server. Put your jar files in that folder. you can access them anywhere.



回答3:

Since you're using jetty, perhaps your best choice is to put your libraries in $jetty.home/lib/ext:

http://docs.codehaus.org/display/JETTY/Classloading

At startup, the jetty runtime will automatically load all jars from the top level $jetty.home/lib, along with certain subdirectories such as $jetty.home/lib/management/, $jetty.home/lib/naming/ etc, which are named explicity in the start.config file contained in the start.jar. In addition, it will recursively load all jars from $jetty.home/lib/ext. So, to add extra jars to jetty, you can simply create a file hierarchy as deep as you wish within $jetty.home/lib/ext to contain these jars. Of course, you can always change this default behaviour by creating your own start.config file and using that instead.