我的ErrorHandler上的Jetty Maven插件ClassNotFoundException

时间:2015-11-30 13:45:36

标签: java maven jetty maven-jetty-plugin

我在此reciepe

之后创建了一个自定义错误处理程序

当我站在我的项目上并执行命令时 ls target/classes/foo/bar/error/MyErrorHandler*

然后显示:target/classes/foo/bar/error/MyErrorHandler.class

我添加了一个带有内容的自定义jetty.xml:

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">

<Configure class="org.eclipse.jetty.server.handler.ContextHandler">
    <Set name="errorHandler">
        <New class="foo.bar.error.MyErrorHandler"/>
    </Set>
</Configure>

这是我的pom.xml

<plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <configuration>
                   <classesDirectory>target/classes</classesDirectory>
                    <httpConnector>
                        <port>9999</port>
                    </httpConnector>
                    <jettyXml>src/test/resources/jetty-errorhandler.xml</jettyXml>
                </configuration>

当我运行mvn jetty:run -X

我收到以下错误:

[DEBUG] parse: file:/home/vagrant/git/seopp/seopp-kunde/src/test/resources/jetty-errorhandler.xml
[DEBUG] parsing: sid=file:/home/vagrant/git/seopp/seopp-kunde/src/test/resources/jetty-errorhandler.xml,pid=null
[DEBUG] resolveEntity(-//Jetty//Configure//EN, http://www.eclipse.org/jetty/configure.dtd)
[DEBUG] Redirected entity http://www.eclipse.org/jetty/configure.dtd --> jar:file:/var/cache/maven_repository/org/eclipse/jetty/jetty-xml/9.2.11.v20150529/jetty-xml-9.2.11.v20150529.jar!/org/eclipse/jetty/xml/configure_9_0.dtd
[WARNING] Config error at <Set name="errorHandler">
        <New class="foo.bar.error.MyErrorHandler"/>
    </Set>
[INFO] Jetty server exiting.

Caused by: java.lang.ClassNotFoundException: foo.bar.error.MyErrorHandler
    at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:50)
    at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:271)
    at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:247)
    at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:239)
    at org.eclipse.jetty.util.Loader.loadClass(Loader.java:86)
    at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.nodeClass(XmlConfiguration.java:364)
    at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.newObj(XmlConfiguration.java:754)
    at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.itemValue(XmlConfiguration.java:1125)

为什么找不到我的MyErrorHandle文件? 它位于我的target / classes目录中,路径正确。

1 个答案:

答案 0 :(得分:2)

尽管我仍然想知道是否存在更好的解决方案,但我最终还是让它发挥了作用。 对我来说,解决方案似乎与Maven插件类路径管理有关,而不是与Jetty本身有关。 Maven插件将classpath添加到它实际定义为插件的依赖项的内容中。它显然也适用于Jetty插件(除非它还实现了一些通过配置启用的其他机制,仍有待发现)。

我创建了一个示例项目并使用了您提供的配置,具有相同的ClassNotFoundException。我解决了它添加Jetty插件的依赖项目本身(唯一的解决方案?),即提供自定义处理程序类的那个。

工作POM下方:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sample</groupId>
    <artifactId>jetty-error</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <build>
        <plugins>
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.2.8.v20150217</version>
                <configuration>
                    <scanIntervalSeconds>10</scanIntervalSeconds>
                    <webApp>
                        <contextPath>/jetty-error</contextPath>
                    </webApp>
                    <httpConnector>
                        <port>7777</port>
                    </httpConnector>
                    <classesDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</classesDirectory>
                    <jettyXml>src/main/resources/jetty.xml</jettyXml>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.eclipse.jetty</groupId>
                        <artifactId>jetty-util</artifactId>
                        <version>9.2.8.v20150217</version>
                    </dependency>
                    <dependency>
                        <groupId>com.sample</groupId>
                        <artifactId>jetty-error</artifactId>
                        <version>0.0.1-SNAPSHOT</version>
                        <scope>system</scope>
                        <systemPath>${basedir}/lib/jetty-error-0.0.1-SNAPSHOT.jar</systemPath>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>9.2.8.v20150217</version>
        </dependency>
    </dependencies>
</project>

注意:我的打包是war,但它不应该有所作为。在这种情况下,我还使用system范围来获取插件依赖关系,没关系,只是为了快速使其工作(我的公司maven存储库存在问题,而且maven没有查找它首先是缓存,但我不想进一步调查,这不是本练习的目标。)

因此,为了进行快速测试,我暂时从项目中创建了一个jar并添加到lib目录中,但它可以很容易地自动化作为构建的一部分(我真的想要证明它需要成为Jetty Maven插件的一部分而不是Jetty服务器的一部分,以使其通过jetty:run)工作。

在我的简单错误处理程序下面:

package com.sample.jetty;

import java.io.IOException;
import java.io.Writer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.ErrorHandler;

public class MyErrorHandler extends ErrorHandler {

    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        response.getOutputStream().println("error!");
    }

    public void handleErrorPage(HttpServletRequest request, Writer writer, int code, String message)
            throws IOException {
        writer.write("error!");
    }

    public void writeErrorPage(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks)
            throws IOException {
        writer.write("error!");
    }

    public void writeErrorPageHead(HttpServletRequest request, Writer writer, int code, String message)
            throws IOException {
        writer.write("error!");
    }

    public void writeErrorPageBody(HttpServletRequest request, Writer writer, int code, String message,
            boolean showStacks) throws IOException {
        writer.write("error!");
    }

    public void writeErrorPageMessage(HttpServletRequest request, Writer writer, int code, String message, String uri)
            throws IOException {
        writer.write("error!");
    }

    public void writeErrorPageStacks(HttpServletRequest request, Writer writer) throws IOException {
        writer.write("error!");
    }

}

在您的配置中使用它没有找到类的异常。我还通过以下jetty配置(jetty.xml)将其设置为全局:

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
"http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">

  <Call name="addBean">
    <Arg>
      <New class="com.sample.jetty.MyErrorHandler">
        <Set name="server"><Ref refid="Server" /></Set>
      </New>
    </Arg>
  </Call>
</Configure>

然后键入错误的地址(即http://localhost:7777/whatever),然后我从自定义错误处理程序中获取了error!消息(它可以正常工作!)。

所以,结论是:类必须是插件类路径的一部分,因为实际上在运行jetty:run时我们正在运行Maven插件。

我的上面的示例可以进一步改进(生成jar /在更标准的maven方法/文件夹中加载jar(即,不是系统范围);使用多模块maven项目,在模块中具有错误处理程序和另一个模块中的jetty插件,以便依赖于该模块;等等,但原理可能是相同的。这是一项具有挑战性和良好的调查。可怜的教程和在线文档对这个主题没什么帮助。