2017-07-10 1 views
0

Lors de la création d'une bibliothèque Tomcat contenant un filtre pour créer journal personnalisé, voici ce que je faisais:Tomcat ne pas trouver bibliothèque personnalisée contenant un filtre

  • Compilé (mvn package) une bibliothèque JAR contenant un filtre unique fichier et le mettre dans le dossier global de Tomcat lib
  • Defined le filtre dans le fichier global de Tomcat web.xml
  • Restarted Tomcat pour vous assurer que les modifications prennent effet

reçu cette erreur:

10-Jul-2017 15:46:32.591 SEVERE [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.core.StandardContext.filterStart Exception starting filter [ReqRespDumpFilter] 
java.lang.NoClassDefFoundError: Could not initialize class com.example.ReqRespDumpFilter 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
    at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:120) 
    at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:262) 
    at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108) 
    at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4481) 
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5121) 
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) 
    at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3690) 
    at org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1404) 
    at org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1377) 
    at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1613) 
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:304) 
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123) 
    at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1172) 
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1394) 
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1398) 
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1366) 
    at java.lang.Thread.run(Thread.java:748) 
10-Jul-2017 16:58:11.581 SEVERE [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.core.StandardContext.startInternal One or more Filters failed to start. Full details will be found in the appropriate container log file 

Le JAR désarchivée:

JAR unarchived

configuration globale de Tomcat tomcat/conf/web.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
         http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" 
    version="4.0"> 
    ... 
    <filter> 
    <filter-name>ReqRespDumpFilter</filter-name> 
    <filter-class>com.example.ReqRespDumpFilter</filter-class> 
    </filter> 

    <filter-mapping> 
    <filter-name>ReqRespDumpFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
    </filter-mapping> 
    ... 
</web-app> 

pom.xml utilisé pour compiler la bibliothèque:

<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/maven-v4_0_0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 
    <groupId>com.example</groupId> 
    <artifactId>ReqRespDumpFilter</artifactId> 
    <packaging>jar</packaging> 
    <version>1.0-SNAPSHOT</version> 
    <name>ReqRespDumpFilter Maven Webapp</name> 
    <url>http://maven.apache.org</url> 
    <dependencies> 
     <!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api --> 
     <dependency> 
      <groupId>javax.servlet</groupId> 
      <artifactId>servlet-api</artifactId> 
      <version>2.5</version> 
      <scope>provided</scope> 
     </dependency> 
     <!-- https://mvnrepository.com/artifact/log4j/log4j --> 
     <dependency> 
      <groupId>log4j</groupId> 
      <artifactId>log4j</artifactId> 
      <version>1.2.17</version> 
     </dependency> 
     <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> 
     <dependency> 
      <groupId>commons-io</groupId> 
      <artifactId>commons-io</artifactId> 
      <version>2.4</version> 
     </dependency> 
    </dependencies> 
    <build> 
     <finalName>ReqRespDumpFilter</finalName> 
     <sourceDirectory>src</sourceDirectory> 
     <plugins> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-compiler-plugin</artifactId> 
       <version>3.1</version> 
       <configuration> 
        <source>1.8</source> 
        <target>1.8</target> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 
</project> 

ReqRespDumpFilter/src/com/example/ReqRespDumpFilter.java code source du filtre:

package com.example; 

import java.io.BufferedReader; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.io.PrintWriter; 
import java.util.Enumeration; 
import java.util.HashMap; 
import java.util.Locale; 
import java.util.Map; 

import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletException; 
import javax.servlet.ServletInputStream; 
import javax.servlet.ServletOutputStream; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.Cookie; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletRequestWrapper; 
import javax.servlet.http.HttpServletResponse; 

import org.apache.commons.io.output.TeeOutputStream; 
import org.apache.log4j.Logger; 

public class ReqRespDumpFilter implements Filter { 


    private static final Logger logger = Logger.getLogger(ReqRespDumpFilter.class); 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException { 
    } 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws IOException, ServletException { 
     try { 
      HttpServletRequest httpServletRequest = (HttpServletRequest) request; 
      HttpServletResponse httpServletResponse = (HttpServletResponse) response; 

      Map<String, String> requestMap = this.getTypesafeRequestMap(httpServletRequest); 
      BufferedRequestWrapper bufferedReqest = new BufferedRequestWrapper(httpServletRequest); 
      BufferedResponseWrapper bufferedResponse = new BufferedResponseWrapper(httpServletResponse); 

      final StringBuilder logMessage = new StringBuilder("REST Request - ") 
        .append("[HTTP METHOD:") 
        .append(httpServletRequest.getMethod()) 
        .append("] [PATH INFO:") 
        .append(httpServletRequest.getPathInfo()) 
        .append("] [REQUEST PARAMETERS:") 
        .append(requestMap) 
        .append("] [REQUEST BODY:") 
        .append(bufferedReqest.getRequestBody()) 
        .append("] [REMOTE ADDRESS:") 
        .append(httpServletRequest.getRemoteAddr()) 
        .append("]"); 

      chain.doFilter(bufferedReqest, bufferedResponse); 
      logMessage.append(" [RESPONSE:").append(bufferedResponse.getContent()).append("]"); 
      logger.debug(logMessage); 
     } catch (Throwable a) { 
      logger.error(a); 
     } 
    } 


    private Map<String, String> getTypesafeRequestMap(HttpServletRequest request) { 
     Map<String, String> typesafeRequestMap = new HashMap<String, String>(); 
     Enumeration<?> requestParamNames = request.getParameterNames(); 
     while (requestParamNames.hasMoreElements()) { 
      String requestParamName = (String) requestParamNames.nextElement(); 
      String requestParamValue = request.getParameter(requestParamName); 
      typesafeRequestMap.put(requestParamName, requestParamValue); 
     } 
     return typesafeRequestMap; 
    } 


    @Override 
    public void destroy() { 
    } 


    private static final class BufferedRequestWrapper extends HttpServletRequestWrapper { 

     private ByteArrayInputStream bais = null; 
     private ByteArrayOutputStream baos = null; 
     private BufferedServletInputStream bsis = null; 
     private byte[] buffer = null; 


     public BufferedRequestWrapper(HttpServletRequest req) throws IOException { 
      super(req); 
      // Read InputStream and store its content in a buffer. 
      InputStream is = req.getInputStream(); 
      this.baos = new ByteArrayOutputStream(); 
      byte buf[] = new byte[1024]; 
      int letti; 
      while ((letti = is.read(buf)) > 0) { 
       this.baos.write(buf, 0, letti); 
      } 
      this.buffer = this.baos.toByteArray(); 
     } 


     @Override 
     public ServletInputStream getInputStream() { 
      this.bais = new ByteArrayInputStream(this.buffer); 
      this.bsis = new BufferedServletInputStream(this.bais); 
      return this.bsis; 
     } 


     String getRequestBody() throws IOException { 
      BufferedReader reader = new BufferedReader(new InputStreamReader(this.getInputStream())); 
      String line = null; 
      StringBuilder inputBuffer = new StringBuilder(); 
      do { 
       line = reader.readLine(); 
       if (null != line) { 
        inputBuffer.append(line.trim()); 
       } 
      } while (line != null); 
      reader.close(); 
      return inputBuffer.toString().trim(); 
     } 

    } 


    private static final class BufferedServletInputStream extends ServletInputStream { 

     private ByteArrayInputStream bais; 

     public BufferedServletInputStream(ByteArrayInputStream bais) { 
      this.bais = bais; 
     } 

     @Override 
     public int available() { 
      return this.bais.available(); 
     } 

     @Override 
     public int read() { 
      return this.bais.read(); 
     } 

     @Override 
     public int read(byte[] buf, int off, int len) { 
      return this.bais.read(buf, off, len); 
     } 


    } 

    public class TeeServletOutputStream extends ServletOutputStream { 

     private final TeeOutputStream targetStream; 

     public TeeServletOutputStream(OutputStream one, OutputStream two) { 
      targetStream = new TeeOutputStream(one, two); 
     } 

     @Override 
     public void write(int arg0) throws IOException { 
      this.targetStream.write(arg0); 
     } 

     public void flush() throws IOException { 
      super.flush(); 
      this.targetStream.flush(); 
     } 

     public void close() throws IOException { 
      super.close(); 
      this.targetStream.close(); 
     } 
    } 


    public class BufferedResponseWrapper implements HttpServletResponse { 

     HttpServletResponse original; 
     TeeServletOutputStream tee; 
     ByteArrayOutputStream bos; 

     public BufferedResponseWrapper(HttpServletResponse response) { 
      original = response; 
     } 

     public String getContent() { 
      return bos.toString(); 
     } 

     public PrintWriter getWriter() throws IOException { 
      return original.getWriter(); 
     } 

     public ServletOutputStream getOutputStream() throws IOException { 
      if (tee == null) { 
       bos = new ByteArrayOutputStream(); 
       tee = new TeeServletOutputStream(original.getOutputStream(), bos); 
      } 
      return tee; 

     } 

     @Override 
     public String getCharacterEncoding() { 
      return original.getCharacterEncoding(); 
     } 

     @Override 
     public String getContentType() { 
      return original.getContentType(); 
     } 

     @Override 
     public void setCharacterEncoding(String charset) { 
      original.setCharacterEncoding(charset); 
     } 

     @Override 
     public void setContentLength(int len) { 
      original.setContentLength(len); 
     } 

     @Override 
     public void setContentType(String type) { 
      original.setContentType(type); 
     } 

     @Override 
     public void setBufferSize(int size) { 
      original.setBufferSize(size); 
     } 

     @Override 
     public int getBufferSize() { 
      return original.getBufferSize(); 
     } 

     @Override 
     public void flushBuffer() throws IOException { 
      tee.flush(); 
     } 

     @Override 
     public void resetBuffer() { 
      original.resetBuffer(); 
     } 

     @Override 
     public boolean isCommitted() { 
      return original.isCommitted(); 
     } 

     @Override 
     public void reset() { 
      original.reset(); 
     } 

     @Override 
     public void setLocale(Locale loc) { 
      original.setLocale(loc); 
     } 

     @Override 
     public Locale getLocale() { 
      return original.getLocale(); 
     } 

     @Override 
     public void addCookie(Cookie cookie) { 
      original.addCookie(cookie); 
     } 

     @Override 
     public boolean containsHeader(String name) { 
      return original.containsHeader(name); 
     } 

     @Override 
     public String encodeURL(String url) { 
      return original.encodeURL(url); 
     } 

     @Override 
     public String encodeRedirectURL(String url) { 
      return original.encodeRedirectURL(url); 
     } 

     @SuppressWarnings("deprecation") 
     @Override 
     public String encodeUrl(String url) { 
      return original.encodeUrl(url); 
     } 

     @SuppressWarnings("deprecation") 
     @Override 
     public String encodeRedirectUrl(String url) { 
      return original.encodeRedirectUrl(url); 
     } 

     @Override 
     public void sendError(int sc, String msg) throws IOException { 
      original.sendError(sc, msg); 
     } 

     @Override 
     public void sendError(int sc) throws IOException { 
      original.sendError(sc); 
     } 

     @Override 
     public void sendRedirect(String location) throws IOException { 
      original.sendRedirect(location); 
     } 

     @Override 
     public void setDateHeader(String name, long date) { 
      original.setDateHeader(name, date); 
     } 

     @Override 
     public void addDateHeader(String name, long date) { 
      original.addDateHeader(name, date); 
     } 

     @Override 
     public void setHeader(String name, String value) { 
      original.setHeader(name, value); 
     } 

     @Override 
     public void addHeader(String name, String value) { 
      original.addHeader(name, value); 
     } 

     @Override 
     public void setIntHeader(String name, int value) { 
      original.setIntHeader(name, value); 
     } 

     @Override 
     public void addIntHeader(String name, int value) { 
      original.addIntHeader(name, value); 
     } 

     @Override 
     public void setStatus(int sc) { 
      original.setStatus(sc); 
     } 

     @SuppressWarnings("deprecation") 
     @Override 
     public void setStatus(int sc, String sm) { 
      original.setStatus(sc, sm); 
     } 

    } 

} 
+0

Voyez-vous le fichier JAR dans le dossier Tomcat/lib? Je suppose que ce n'est pas là à l'exécution. La JVM ne peut pas le trouver; ce n'est pas dans l'endroit que vous pensez qu'il devrait être. – duffymo

+0

Le fichier JAR doit avoir la structure de votre package avec les fichiers .class. Sinon, vous avez un problème d'emballage Maven. Le type de package est-il "jar"? – duffymo

+0

Désolé, j'ai fait une erreur dans mon précédent commentaire. Lorsque vous utilisez la même commande pour désarchiver, la bibliothèque personnalisée a la même structure que les bibliothèques natives. –

Répondre

2

Vous obtenez:

java.lang.NoClassDefFoundError: Could not initialize class com.example.ReqRespDumpFilter 

parce que cette classe contient un initialiseur statique pour une instance de org.apache.log4j.Logger.

Ni log4j ou commons-io sont présents dans une distribution standard de Tomcat de sorte que vous devez vous assurer qu'ils sont également présents dans votre répertoire tomcat lib.

De plus, vous devez copier/déplacer votre fichier log4j.properties/log4j.xml dans le répertoire tomcat conf afin qu'il soit accessible pour configurer correctement votre journalisation. Vous pouvez créer log4j <scope>provided</scope> dans toutes vos applications afin de centraliser la configuration.