How do you get embedded Jetty 9 to successfully re

2019-03-12 18:12发布

I'm packaging a Web Application Archive (.war) so that it can be started via java -jar webapp.war in a shell by launching an embedded copy of Jetty 9 using this code in a main class:

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();

However, I'm running into this error when the first JSP containing a JSTL taglib declaration gets compiled:

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

The first couple lines of that JSP are as follows:

<%@ 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" %>

I've looked around quite a bit (this doesn't seem to be a new issue) and have tried the following solutions:

  • Slimming down my dependencies and looking for conflicts (currently I'm only depending on jetty-server, jetty-webapp, and jetty-jsp, all version 9.0.4.v20130625)
  • Specifying an explicit <taglib> mapping in the webapp's web.xml file that points to JSTL directly (got this idea from reading the JSP spec)
  • Modifying the server classpath as per this answer
  • Taking advantage of methods of WebAppContext such as addServerClass and setParentLoaderPriority

According to Jetty's documentation, using JSTL should just work, but I think the embedded context may be changing the way JSTL gets loaded and causing it to fail.

Would appreciate any ideas or suggestions. This setup would be replacing an older setup that did the same thing successfully on Windows but was not functioning on Linux due to the inclusion of an old dependency that brought in this bug. Unfortunately, I haven't been able to find a quick replacement for that dependency (groupId org.mortbay.jetty artifactId jsp-2.1-glassfish version 2.1.v20100127) that doesn't introduce the JSTL URI stack trace mentioned above.

UPDATE: I've found a suboptimal solution. A downgrade to Jetty 7 inspired by this thread now has me up and running. This is great news, but it's discouraging that if I later required any functionality exclusive to Jetty 8 or Jetty 9 that I'd have to scrap this deployment infrastructure. Any insight on JSTL taglib issue in Jetty 9 would still be appreciated.

8条回答
干净又极端
2楼-- · 2019-03-12 18:45
WebAppContext context = new WebAppContext();      
final URL url = getClass().getProtectionDomain().getCodeSource().getLocation();
if (url != null) {
    context.getMetaData().addWebInfJar(JarResource.newResource(url));
}

Add the fat-jar as a WEB-INF jar, let the MetaInfConfiguration to find the *.tld files.

Reference:

查看更多
地球回转人心会变
3楼-- · 2019-03-12 18:48

I was having this exact problem. And I solved it in the most unusual way.

I am using Maven as the build tool, but here is how I was building my self-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>

But like yourself I was getting that error. After Googling the death out of it after 2 days I found this - http://internna.blogspot.co.uk/2011/08/step-by-step-executable-war-files.html

By switching out the jetty-jsp dependency for this one:

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

It all started magically working!

As of this moment I can't explain why it does work. But I am keen to find out

查看更多
登录 后发表回答