2013-07-16 7 views
14

che sto confezionamento di una Web Application Archive (.war) in modo che possa essere avviato tramite java -jar webapp.war in un guscio con il lancio di una copia incorporata di Jetty 9 utilizzando questo codice in una classe principale:Come si ottiene il Jetty 9 incorporato per risolvere correttamente l'URI JSTL?

int port = Integer.parseInt(System.getProperty("port", "80")); // I know this has implications :) 
String contextPath = System.getProperty("contextPath", ""); 
Server server = new Server(port); 
ProtectionDomain domain = Deployer.class.getProtectionDomain(); 
URL location = domain.getCodeSource().getLocation(); 
WebAppContext webapp = new WebAppContext(); 
webapp.setContextPath("/" + contextPath); 
webapp.setWar(location.toExternalForm()); 
server.setHandler(webapp); 
server.start(); 
server.join(); 

Tuttavia, io corro in questo errore quando il primo JSP contenente una dichiarazione JSTL taglib viene compilato:

org.apache.jasper.JasperException: /WEB-INF/html/user/login.jsp(2,62) PWC6188: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application 
at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:92) 
at org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:378) 
at org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:172) 
at org.apache.jasper.compiler.TagLibraryInfoImpl.generateTLDLocation(TagLibraryInfoImpl.java:431) 
at org.apache.jasper.compiler.TagLibraryInfoImpl.<init>(TagLibraryInfoImpl.java:240) 
at org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:502) 
at org.apache.jasper.compiler.Parser.parseDirective(Parser.java:582) 
at org.apache.jasper.compiler.Parser.parseElements(Parser.java:1652) 
at org.apache.jasper.compiler.Parser.parse(Parser.java:185) 
at org.apache.jasper.compiler.ParserController.doParse(ParserController.java:244) 
at org.apache.jasper.compiler.ParserController.parse(ParserController.java:145) 
at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:212) 
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:451) 
at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:625) 
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374) 
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:492) 
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:378) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848) 
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:698) 
etc... 

la coppia prime righe di quel JSP sono i seguenti:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" isELIgnored="false" %> 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 

Ho guardato in giro un bel po '(questo non sembra essere una nuova emissione) e ho provato le seguenti soluzioni:

  • snellimento mie dipendenze e alla ricerca di conflitti (attualmente sto solo in funzione su jetty-server, jetty-webapp e jetty-jsp, tutte le versioni 9.0.4.v20130625)
  • Specifica di un esplicito <taglib> mappatura nel file web.xml del webapp che punta direttamente a JSTL (ottenuto questa idea dalla lettura della specifica JSP)
  • modifica del percorso di classe server come per this answer
  • Approfittando di metodi di WebAppContext quali addServerClass e setParentLoaderPriority

Secondo Jetty's documentation, usando JSTL dovrebbe funzionare, ma penso che il contesto incorporato può cambiare il modo in cui viene caricato JSTL e causando il fallimento.

Apprezzerebbero qualsiasi idea o suggerimento. Questa installazione sostituirà una vecchia configurazione che ha fatto la stessa cosa con successo su Windows ma non funzionava su Linux a causa dell'inclusione di una vecchia dipendenza che portava this bug. Sfortunatamente, non sono stato in grado di trovare una sostituzione rapida per tale dipendenza (groupIdartefactId jsp-2.1-glassfish versione 2.1.v20100127) che non introduce la traccia dello stack URI JSTL menzionata sopra.

UPDATE: Ho trovato una soluzione non ottimale. Un downgrade a Jetty 7 ispirato a this thread ora mi ha installato e funzionante. Questa è un'ottima notizia, ma è scoraggiante che, se in seguito avessi richiesto una funzionalità esclusiva per Jetty 8 o Jetty 9, avrei dovuto eliminare questa infrastruttura di distribuzione. Qualsiasi intuizione sul problema del taglib JSTL in Jetty 9 sarebbe comunque apprezzata.

risposta

1

Purtroppo, nessuna delle risposte finora hanno lavorato per me. Ma alla fine ho trovato una soluzione al mio problema. Questo suonerà come un hack, e sembra decisamente uno.

Ma se riesco a impostare tutto esattamente come ho descritto nella mia domanda, fino al punto in cui la JSTL non si risolverà, posso quindi fare un passo che fa funzionare tutto, quasi come per magia.

Questo passaggio di indurimento sta modificando l'estensione sul file .war su .jar. Una volta che lo faccio, la JSTL si risolve perfettamente e tutto funziona.

Quindi in questo momento produco uno .war che è possibile inserire in un contenitore servlet o è possibile rinominare in .jar ed eseguire autonomamente. Funziona su Unix e Windows, mentre il modo in cui lo stavo facendo prima non funzionava su Unix a causa di un bug presente nella libreria jsp-2.1-glassfish menzionata da James Cook.

I bit rilevanti dal mio pom:

<properties> 
    <jetty.version>9.0.5.v20130815</jetty.version> 
    <war.class>com.domain.package.DeployWebapp</war.class> 
    <war.class.path>com/domain/package</war.class.path> 
</properties>  

<dependency> 
    <groupId>org.eclipse.jetty</groupId> 
    <artifactId>jetty-server</artifactId> 
    <version>${jetty.version}</version> 
    <scope>provided</scope> 
</dependency> 

<dependency> 
    <groupId>org.eclipse.jetty</groupId> 
    <artifactId>jetty-webapp</artifactId> 
    <version>${jetty.version}</version> 
    <scope>provided</scope> 
</dependency> 

<dependency> 
    <groupId>org.eclipse.jetty</groupId> 
    <artifactId>jetty-jsp</artifactId> 
    <version>${jetty.version}</version> 
    <scope>provided</scope> 
</dependency> 

<plugin> 
    <artifactId>maven-antrun-plugin</artifactId> 
    <version>1.7</version> 
    <executions> 
     <execution> 
      <id>main-class-placement</id> 
      <phase>prepare-package</phase> 
      <configuration> 
       <tasks> 
        <move todir="${project.build.directory}/${project.artifactId}-${project.version}/${war.class.path}"> 
        <fileset dir="${project.build.directory}/classes/${war.class.path}"> 
         <include name="DeployWebapp.class" /> 
        </fileset> 
       </move> 
         </tasks> 
       </configuration> 
       <goals> 
        <goal>run</goal> 
       </goals> 
      </execution> 
    </executions> 
</plugin> 

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-dependency-plugin</artifactId> 
    <version>2.3</version> 
    <executions> 
     <execution> 
      <id>jetty-classpath</id> 
      <phase>prepare-package</phase> 
      <goals> 
       <goal>unpack-dependencies</goal> 
      </goals> 
      <configuration> 
       <includeGroupIds>org.eclipse.jetty,javax.servlet,javax.el,org.glassfish.web,org.eclipse.jetty.orbit,org.ow2.asm,javax.annotation</includeGroupIds> 
       <outputDirectory> 
        ${project.build.directory}/${project.artifactId}-${project.version} 
       </outputDirectory> 
      </configuration> 
     </execution> 
    </executions> 
</plugin> 

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-war-plugin</artifactId> 
    <version>2.4</version> 
    <configuration> 
     <attachClasses>true</attachClasses> 
     <archiveClasses>true</archiveClasses> 
     <archive> 
      <manifest> 
       <mainClass>${war.class}</mainClass> 
      </manifest> 
     </archive> 
     <packagingExcludes>META-INF/*.SF</packagingExcludes> 
     <packagingExcludes>META-INF/*.DSA</packagingExcludes> 
     <packagingExcludes>META-INF/*.RSA</packagingExcludes> 
    </configuration> 
</plugin> 
1

Ho appena creato un semplice jsp con ta taglib durante l'utilizzo. Quindi ha creato l'app del server e funziona. Quindi, penso che non sia un taglib che causa il problema.

public static void main(String[] args) throws Exception { 
    Server server = new Server(8680); 
    HandlerCollection handlers = new HandlerCollection(); 
    server.setHandler(handlers); 
    ContextHandlerCollection chc = new ContextHandlerCollection(); 
    handlers.addHandler(chc); 
    WebAppContext webapp = new WebAppContext(); 
    webapp.getInitParams().put("org.eclipse.jetty.servlet.Default.useFileMappedBuffer",  
    "false"); 
    webapp.setContextPath("/WebAppMng01"); 
    //URL url = ManagedServer.class.getResource("/WebAppMng01/build/web"); 
    URL url = ManagedServer.class.getResource("/WebAppMng01/dist/WebAppMng01.war"); 
    if (url != null) { 
     webapp.setWar(url.toExternalForm()); 
     chc.addHandler(webapp); 
    } 
    server.start(); 
    server.join(); 
} 
3

Ho avuto lo stesso problema a lanciare Jetty da un test Surefire; il problema era che Jetty 9 non guarda i manifesti di nessun file jar tranne in WEB-INF, che è incompatibile con il modo in cui stavo scrivendo i miei test.

Per aggirare il problema, ho scritto un po 'di codice per trovare i file jar dal manifest e inserirli in un nuovo URLClassLoader intermedio.

Questo è ciò che il mio funzionale funzione di configurazione di test si è conclusa per assomigliare a farlo funzionare con Jetty 9:

@Before @SuppressWarnings("unchecked") 
public void setUp() throws Exception { 

    WebAppContext ctx = new WebAppContext("src/main/webapp", "/"); 

    Server server = new Server(9000); 

    ctx.setServer(server); 
    server.setHandler(ctx); 

    ctx.preConfigure(); 

    ctx.addOverrideDescriptor("src/main/webapp/WEB-INF/tests-web.xml");  

    // Replace classloader with a new classloader with all URLs in manifests 
    // from the parent loader bubbled up so Jasper looks at them. 
    ClassLoader contextClassLoader = ctx.getClassLoader(); 
    ClassLoader parentLoader = contextClassLoader.getParent(); 
    if (contextClassLoader instanceof WebAppClassLoader && 
     parentLoader instanceof URLClassLoader) { 
     LinkedList<URL> allURLs = 
      new LinkedList<URL>(Arrays.asList(((URLClassLoader)parentLoader).getURLs())); 
     for (URL url : ((LinkedList<URL>)allURLs.clone())) { 
     try { 
      URLConnection conn = new URL("jar:" + url.toString() + "!/").openConnection(); 
      if (!(conn instanceof JarURLConnection)) 
      continue; 
      JarURLConnection jconn = (JarURLConnection)conn; 
      Manifest jarManifest = jconn.getManifest(); 
      String[] classPath = ((String)jarManifest.getMainAttributes().getValue("Class-Path")).split(" "); 

      for (String cpurl : classPath) 
      allURLs.add(new URL(url, cpurl)); 
     } catch (IOException e) {} catch (NullPointerException e) {} 
     } 

     ctx.setClassLoader(
      new WebAppClassLoader(
       new URLClassLoader(allURLs.toArray(new URL[]{}), parentLoader), 
       ((WebAppClassLoader)contextClassLoader).getContext())); 
    } 

    server.start(); 
} 

mio esempio di codice viene inserito nel dominio pubblico - lo si può utilizzare nel proprio codice (attribuzione apprezzata ma non richiesta).

+0

Questa soluzione funziona per Jetty 9.0, ma non 9.1 –

+0

Inoltre, non causa problemi per Jetty 8.1 –

3

Dopo aver giocato con la soluzione di a1kmm e aver finito con NullPointers ho notato che non ho impostato un Classloader su WebAppContext. Usando la seguente riga non ho più bisogno dell'installazione di scansione personalizzata per classloading/manifest.

webAppContext.setClassLoader(new WebAppClassLoader(getClass().getClassLoader(), webAppContext)); 
2

Stavo avendo questo problema esatto. E l'ho risolto nel modo più insolito.

Sto usando Maven come strumento di compilazione, ma ecco come stavo costruendo la mia auto-exec WAR.

<profile> 
     <id>Jetty_9</id> 
     <properties> 
      <jetty9.version>9.0.4.v20130625</jetty9.version> 
     </properties> 
     <dependencies> 
      <dependency> 
       <groupId>ch.qos.logback</groupId> 
       <artifactId>logback-classic</artifactId> 
       <version>${logback.version}</version> 
       <scope>provided</scope> 
      </dependency> 
      <dependency> 
       <groupId>ch.qos.logback</groupId> 
       <artifactId>logback-access</artifactId> 
       <version>${logback.version}</version> 
       <scope>provided</scope> 
      </dependency> 
      <dependency> 
       <groupId>ch.qos.logback</groupId> 
       <artifactId>logback-core</artifactId> 
       <version>${logback.version}</version> 
       <scope>provided</scope> 
      </dependency> 
      <dependency> 
       <groupId>org.slf4j</groupId> 
       <artifactId>slf4j-api</artifactId> 
       <version>${slf4j.version}</version> 
       <scope>provided</scope> 
      </dependency> 

      <dependency> 
       <groupId>org.eclipse.jetty.orbit</groupId> 
       <artifactId>javax.servlet</artifactId> 
       <version>3.0.0.v201112011016</version> 
       <scope>provided</scope> 
      </dependency> 
      <dependency> 
       <groupId>org.eclipse.jetty</groupId> 
       <artifactId>jetty-webapp</artifactId> 
       <version>${jetty9.version}</version> 
       <scope>provided</scope> 
      </dependency> 
      <dependency> 
       <groupId>org.eclipse.jetty</groupId> 
       <artifactId>jetty-plus</artifactId> 
       <version>${jetty9.version}</version> 
       <scope>provided</scope> 
      </dependency> 
      <dependency> 
       <groupId>org.eclipse.jetty</groupId> 
       <artifactId>jetty-jsp</artifactId> 
       <version>${jetty9.version}</version> 
      </dependency>    
     </dependencies> 
     <build> 
      <plugins> 
       <plugin> 
        <artifactId>maven-compiler-plugin</artifactId> 
        <version>2.3.2</version> 
        <configuration> 
         <source>${compileSource}</source> 
         <target>${compileSource}</target> 
        </configuration> 
       </plugin> 
       <plugin> 
        <groupId>org.apache.maven.plugins</groupId> 
        <artifactId>maven-antrun-plugin</artifactId> 
        <version>1.7</version> 
        <executions> 
         <execution> 
          <id>main-class-placement</id> 
          <phase>prepare-package</phase> 
          <configuration> 
           <target> 
            <move todir="${project.build.directory}/${project.build.finalName}/"> 
             <fileset dir="${project.build.directory}/classes/"> 
              <include name="Main.class"/> 
             </fileset> 
            </move> 
           </target> 
          </configuration> 
          <goals> 
           <goal>run</goal> 
          </goals> 
         </execution> 
        </executions> 
       </plugin> 
       <plugin> 
        <groupId>org.apache.maven.plugins</groupId> 
        <artifactId>maven-dependency-plugin</artifactId> 
        <version>2.6</version> 
        <executions> 
         <execution> 
          <id>jetty-classpath</id> 
          <phase>prepare-package</phase> 
          <goals> 
           <goal>unpack-dependencies</goal> 
          </goals> 
          <configuration> 
           <includeGroupIds> 
            org.eclipse.jetty,org.slf4j,ch.qos 
           </includeGroupIds>          
           <includeScope>provided</includeScope> 
           <excludes>META-INF/*.SF,META-INF/*.RSA,about.html, about_files/**, readme.txt, 
            plugin.properties, jetty-dir.css 
           </excludes> 
           <outputDirectory> 
            ${project.build.directory}/${project.build.finalName} 
           </outputDirectory> 
          </configuration> 
         </execution> 
        </executions> 
       </plugin> 
       <plugin> 
        <groupId>org.apache.maven.plugins</groupId> 
        <artifactId>maven-war-plugin</artifactId> 
        <version>2.3</version> 
        <configuration> 
         <archive> 
          <manifest> 
           <mainClass>Main</mainClass> 
          </manifest> 
         </archive> 
        </configuration> 
        <executions> 
         <execution> 
          <id>default-war</id> 
          <phase>package</phase> 
          <goals> 
           <goal>war</goal> 
          </goals> 
         </execution> 
        </executions> 
       </plugin> 
      </plugins> 
     </build> 
    </profile> 

Ma come te stavo ottenendo quell'errore. Dopo Googling la morte fuori di esso dopo 2 giorni ho trovato questo - http://internna.blogspot.co.uk/2011/08/step-by-step-executable-war-files.html

Passando fuori la dipendenza pontile-jsp per questo uno:

<dependency> 
      <groupId>org.mortbay.jetty</groupId> 
      <artifactId>jsp-2.1-glassfish</artifactId> 
      <version>2.1.v20100127</version> 
</dependency> 

Tutto è iniziato magicamente a lavorare!

A partire da questo momento non posso spiegare perché funziona. Ma sono curioso di scoprire

+0

Ho appena aggiunto jsp-2.1-GlassFish alle mie dipendenze e funziona? – Alexey

+0

Ehi! Mi piacerebbe aiutarti, ma questa risposta essendo oltre 2 anni ormai, la memoria è un po 'confuso. Penso che tutto sia andato avanti da allora. –

7

Quindi ecco un'altra soluzione. Ero alle prese con problemi molto simili, ma ho solo un file di guerra separato e una semplice classe embedder che crea per me un server Jetty e lo avvia indicando eventualmente un file di guerra. Ecco come funziona tutto questo.

  1. file di La guerra non ha alcuna libreria TLD in WEB-INF/lib ed è completamente separato dal miniapplication caricatore.

  2. La classe principale applicazione Loader, che avvia il server e la punta a qualsiasi file guerra ha seguito le dipendenze (Maven):

    <!-- Jetty webapp --> 
        <dependency> 
         <groupId>org.eclipse.jetty</groupId> 
         <artifactId>jetty-webapp</artifactId> 
         <version>${jettyVersion}</version> 
        </dependency> 
    
        <!-- With JSP support --> 
        <dependency> 
         <groupId>org.eclipse.jetty</groupId> 
         <artifactId>jetty-jsp</artifactId> 
         <version>${jettyVersion}</version> 
        </dependency> 
    

  3. La classe di carico in sé appare come :

    Server server = new Server(cncPort); 
    
    WebAppContext webApp = new WebAppContext(); 
    
    webApp.setContextPath(applicationContext); 
    webApp.setWar(jettyHome + "/" + warFile); 
    server.setHandler(webApp); 
    
    try { 
        server.start(); 
        server.join(); 
    } catch (Exception ex) { 
        System.out.println("Failed to start server."); 
        ex.printStackTrace(); 
    } 
    
  4. Il pacchetto risultante nel mio caso si presenta come segue:

    + EmbedderApp 
    | 
    +-- lib 
        - EmbeddedApp.jar <-- JAR with the embedder class 
        - com.sun.el-2.2.0.v201303151357.jar 
        - javax.el-2.2.0.v201303151357.jar 
        - javax.servlet-3.0.0.v201112011016.jar 
        - javax.servlet.jsp-2.2.0.v201112011158.jar 
        - javax.servlet.jsp.jstl-1.2.0.v201105211821.jar 
        - jetty-http-9.0.6.v20130930.jar 
        - jetty-io-9.0.6.v20130930.jar 
        - jetty-jsp-9.0.6.v20130930.jar 
        - jetty-security-9.0.6.v20130930.jar 
        - jetty-server-9.0.6.v20130930.jar 
        - jetty-servlet-9.0.6.v20130930.jar 
        - jetty-util-9.0.6.v20130930.jar 
        - jetty-webapp-9.0.6.v20130930.jar 
        - jetty-xml-9.0.6.v20130930.jar 
        - org.apache.jasper.glassfish-2.2.2.v201112011158.jar 
        - org.apache.taglibs.standard.glassfish-1.2.0.v201112081803.jar 
        - org.eclipse.jdt.core-3.8.2.v20130121.jar 
    
  5. miei dependecies erano semplicemente aggiunto tramite plug-in assemblea come

    <dependencySet> 
        <outputDirectory>lib</outputDirectory> 
        <scope>runtime</scope> 
    </dependencySet> 
    
  6. ho una shell script di avvio di lancio della classe di incorporamento e qui arriva quello che mi ha portato da secoli a capire.

    Ho usato un manifest con classpath incorporato nel jar e ho impostato il mio CLASSPATH=<PATH_TO_APP>\lib\EmbeddedApp.jar assumendo che il reset delle dipendenze faccia parte del mio classpath attraverso il manifest. E stavo ottenendo lo stesso errore URI irrisolvibile.

    Una volta aggiunta la variabile CLASSPATH all'interno del mio script per contenere tutti i vasi esplicitamente ha iniziato a funzionare.

    for jar in ${APP_ROOT}/lib/*.jar; do CLASSPATH=$jar:${CLASSPATH}; done 
    

Spero che questo può salvare qualcuno tempo :-)

+0

Gonfiare il percorso di classe ha lavorato anche per me - grazie mille! Stavo per rinunciare a questo. –

+0

Hehe, mi sento il vostro dolore, mi sono voluti secoli per capire –

0

Sembra che molo incorporato 9 non piace utilizzare automaticamente le voci di percorso di classe dal file eseguibile jar principale. Questo include le librerie taglib. Anche l'aggiunta di voci del percorso di classe direttamente a webappclassloader non sembra funzionare. Per qualsiasi motivo le voci del percorso di classe devono essere aggiunte a un genitore del webappclassloader.

La soluzione più semplice non funziona per me:

webAppContext.setClassLoader(new WebAppClassLoader(getClass().getClassLoader(), webAppContext)); 

Ma la scansione manifesti a mano faceva. Ho riscritto l'esempio di scansione sopra appena ho potuto vedere cosa sta succedendo e provare diverse cose che includerò qui.

//========== create WebAppClassloader with a new parent classloader with all URLs in manifests=================== 
    //search for any secondary class path entries 
    Vector<URL> secondayClassPathURLVector = new Vector<>(); 
    ClassLoader parentClassLoader = this.getClass().getClassLoader(); 
    if(parentClassLoader instanceof URLClassLoader) 
    { 
     URL[] existingURLs = ((URLClassLoader)parentClassLoader).getURLs(); 
     for (URL parentURL : existingURLs) 
     { 
      //if it doesn't end in .jar, then it's probably not going to have Manifest with a Class-Path entry 
      if(parentURL.toString().endsWith(".jar")) 
      { 
       JarURLConnection jarURLConnection = (JarURLConnection) new URL("jar:" + parentURL.toString() + "!/").openConnection(); 
       Manifest jarManifest = jarURLConnection.getManifest(); 
       String classPath = jarManifest.getMainAttributes().getValue("Class-Path"); 
       if(classPath != null) 
       { 
        //Iterate through all of the class path entries and create URLs out of them             
        for (String part : classPath.split(" ")) 
        { 
         //add our full path to the jar file to our classpath list 
         secondayClassPathURLVector.add(new URL(parentURL,part));      
        } 
       } 
      }     
     } 
    } 
    //use our class path entries to create a parent for the webappclassloader that knows how to use or referenced class paths 
    URLClassLoader internalClassPathUrlClassLoader = new URLClassLoader(secondayClassPathURLVector.toArray(new URL[secondayClassPathURLVector.size()]), parentClassLoader); 
    //create a new webapp class loader as a child of our internalClassPathUrlClassLoader. For whatever reason Jetty needs to have a WebAppClassLoader be it's main class loader, 
    //while all of our classpath entries need to be added to the parent class loader 
    WebAppClassLoader webAppClassLoader = new WebAppClassLoader(internalClassPathUrlClassLoader,context); 
    context.setClassLoader(webAppClassLoader); 

Questo dovrebbe sostituire l'esempio embedded-molo-jsp, che semplicemente non funziona per qualsiasi motivo, ma dovrebbe, come tutte le voci del percorso di classe dovrebbe automaticamente incluso nel classpath. Tuttavia, afferma che JSP richiede un caricatore di classe NON system. Quindi posso solo supporre che JSP interrompa la scansione del percorso della classe una volta raggiunto il caricatore del classpath di sistema. Ecco perché dobbiamo effettivamente sostituirlo.

0
WebAppContext context = new WebAppContext();  
final URL url = getClass().getProtectionDomain().getCodeSource().getLocation(); 
if (url != null) { 
    context.getMetaData().addWebInfJar(JarResource.newResource(url)); 
} 

Aggiungere il grasso-vaso come un barattolo WEB-INF, lasciare che il MetaInfConfiguration per trovare i file * TLD.

Riferimento: