Managing multiple banks via WebClubContext extraClasspath

I have a built-in jetty server that hot deploys webapps. When deploying other wars, I add the deployment descriptor.xml file to the directory to configure the webappcontext. I want to add a DIRECTORY of cans to be built elsewhere along the hot deployed war class path (/ extJars). I can see how to do this in the webapp descriptor.xml file and I can do it by specifying individual jars, but I tried several configurations trying to just read ALL jars in that directory and nothing worked. Here is my otherWebApp.xml, we'll call it, with the configuration that works, and commented out the configurations that don't work. Thank.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
    <Configure class="org.eclipse.jetty.webapp.WebAppContext">
        <Set name="war"><SystemProperty name="JETTY_HOME" default="." />/extApps/otherWebApp.war</Set>
        <Set name="contextPath">/otherWebApp</Set>
        <Set name="tempDirectory" ><SystemProperty name="JETTY_HOME" />/jetty/webapps/otherWebApp</Set>  
<Set name="extraClasspath"><SystemProperty name="JETTY_HOME" />/extJars/cadi-core-1.0.12.jar,<SystemProperty name="JETTY_HOME" />/extJars/cadi-aaf-1.0.12.jar,<SystemProperty name="JETTY_HOME" />/extJars/GLCookieDecryption-1.0.jar,<SystemProperty name="JETTY_HOME" />/extJars/rosetta-1.1.1.jar,<SystemProperty name="AJSC_HOME" />/extJars/env-1.4.2.jar,<SystemProperty name="JETTY_HOME" />/extJars/dme2-2.5.22.jar</Set>
<!-- <Set name="extraClasspath"><SystemProperty name="JETTY_HOME" />/extJars/</Set>
    </Configure>  doesn't work -->
<!-- <Set name="extraClasspath"><SystemProperty name="JETTY_HOME" />/extJars/*</Set>
    </Configure> doesn't work -->
<!-- <Set name="extraClasspath"><SystemProperty name="JETTY_HOME" />/extJars/*.jar</Set>
    </Configure>  doesn't work -->
<!-- <Set name="extraClasspath"><SystemProperty name="JETTY_HOME" />/extJars</Set>
    </Configure> doesn't work -->

      

+3


source to share


1 answer


You have 3 options.

1: Parent Loader Priority

In inline mode, tell WebAppContext to use the parent loader priority. (this would mean server classes over webapp classes)

<Configure class="org.eclipse.jetty.webapp.WebAppContext">
  <Set name="contextPath">/example</Set>
  <Set name="war">example.war</Set>
  <Set name="parentLoaderPriority">true</Set>
</Configure>

      

This has a side effect: if the server class does cache information (a common method in many libraries), then this cache is now available to all web applications.

2: Use a custom DeploymentManager binding to manage the WebAppClassloader

Each WebAppContext uses a WebAppClassloader which can be configured to:

  • Extract specific classes from server classloader
  • Indicate what the WebAppContext does if there is a conflict between the webapp and the server.

Since you are using DeploymentManager

this can be standardized with Bindings methods.



The binding itself: ExposeServerCommonBinding.java

package jetty;

import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppLifeCycle;
import org.eclipse.jetty.deploy.graph.Node;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.webapp.WebAppContext;

public class ExposeServerCommonBinding implements AppLifeCycle.Binding
{
    public String[] getBindingTargets()
    {
        return new String[]
        { "deploying" };
    }

    public void processBinding(Node node, App app) throws Exception
    {
        ContextHandler handler = app.getContextHandler();
        if (handler == null)
        {
            throw new NullPointerException("No Handler created for App: " + app);
        }

        if (handler instanceof WebAppContext)
        {
            WebAppContext webapp = (WebAppContext)handler;

            // System classes (or namespaces) present in server classloader to expose to webapp
            webapp.addSystemClass("org.apache.log4j.");
            webapp.addSystemClass("org.slf4j.");
            webapp.addSystemClass("org.apache.commons.logging.");

            // Server classes that cannot be overridden by webapp
            webapp.addServerClass("-org.apache.log4j.");
            webapp.addServerClass("-org.slf4j.");
            webapp.addServerClass("-org.apache.commons.logging.");
        }
    }
}

      

And how to use it

DeploymentManager mgr = new DeploymentManager();

WebAppProvider provider = new WebAppProvider();
provider.setMonitoredDirResource(Resource.newResource(new File("./webapps/")));
mgr.addAppProvider(provider);

mgr.addLifeCycleBinding(new ExposeServerCommonBinding());

      

This method applies to all WebAppContexts that are deployed through the DeploymentManager, allowing these rules to be applied equally to all webapps.

3: Use a custom DeploymentManager binding to manage the extraClasspath interface

Here is another Binding alternative that you can use to prebuild the extraClasspath on the server side, and when the WebApp is deployed, it automatically adds this extraClasspath to the WebApp.

package jetty;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppLifeCycle;
import org.eclipse.jetty.deploy.graph.Node;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.webapp.WebAppContext;

public class CommonExtraClasspathBinding implements AppLifeCycle.Binding
{
    private List<File> extraClasspath = new ArrayList<>();

    public String[] getBindingTargets()
    {
        return new String[] { "deploying" };
    }

    public void addAllJars(File dir)
    {
        for (File file : dir.listFiles())
        {
            if (!file.isFile())
            {
                continue;
            }
            if (file.getName().toLowerCase(Locale.ENGLISH).equals(".jar"))
            {
                addJar(file);
            }
        }
    }

    public void addJar(File jar)
    {
        if (jar.exists() && jar.isFile())
        {
            extraClasspath.add(jar);
        }
    }

    public void processBinding(Node node, App app) throws Exception
    {
        ContextHandler handler = app.getContextHandler();
        if (handler == null)
        {
            throw new NullPointerException("No Handler created for App: " + app);
        }

        if (handler instanceof WebAppContext)
        {
            WebAppContext webapp = (WebAppContext)handler;

            StringBuilder xtraCp = new StringBuilder();
            boolean delim = false;
            for (File cp : extraClasspath)
            {
                if (delim)
                {
                    xtraCp.append(File.pathSeparatorChar);
                }
                xtraCp.append(cp.getAbsolutePath());
                delim = true;
            }

            webapp.setExtraClasspath(xtraCp.toString());
        }
    }
}

      

+2


source







All Articles