2015-11-30 7 views
2

Я создал обработчик ошибок после этой reciepeJetty Maven плагин ClassNotFoundException на моем ErrorHandler

Когда я стою ом моего проекта и выполните команду ls target/classes/foo/bar/error/MyErrorHandler*

Затем он показывает: target/classes/foo/bar/error/MyErrorHandler.class

I добавили пользовательский файл 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 с правильным путем.

ответ

2

Я в конечном итоге сделал это, хотя я все еще задаюсь вопросом, существует ли более приятное решение. Для меня решение кажется более связанным с управлением плагинами в Maven plugin в целом, а не с самим 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> 

Примечание: мой Packaing является 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.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.

Мой пример выше может быть улучшен далее (генерирование банки/загрузка банки в более стандартном подходе/папке maven (то есть не в системной области)), используйте проект мультимодального maven, имеющий обработчик ошибок в модуле и плагин причала в другом модуле, чтобы иметь зависимость от этого модуля и т. д.), но принцип, вероятно, будет таким же. Это было сложное и приятное исследование. Опытные учебные пособия и документация онлайн не очень помогают в этой теме.

+0

Спасибо! Это выглядит многообещающе. Хотя я согласен, его довольно уродливый взлом :) Я попробую его и отчитаю! –

+0

Вы также можете установить страницу с ошибкой в ​​web.xml, хотя это не то же самое, но это предотвращает показ исключений для пользователя. – user1050755