Warm tip: This article is reproduced from serverfault.com, please click

Tomcat. ClassNotFoundException on importing class

发布于 2020-12-03 14:20:51

I am writing my training project on Tomcat based java servlets and jsp's using Visual Studio Code. Now I am working on logging. My project structure looks like this:

webapps
|----ROOT
     |----public
     |----WEB-INF
          |----classes
               |----FamilyTask
                    |----filters
                         |----AccessFilter.java
                         |----compile_filter.bat
                    |----lib
                         |----Log.java
                         |----compile_class.bat
                    |----servlets
                         |----compile_servlet.bat
                         |----LoginServlet.java
          |----lib
          |----web.xml

Class AccessFilter.java realizes logging system. Here is code of AccessFilter.java:

package FamilyTask.filters;

import ...

import FamilyTask.lib.Log;

public class AccessFilter implements Filter 
{
    ...
    ...
    ...

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException 
    {
            
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        String path = req.getServletPath();

        FamilyTask.lib.Log.Info("#INFO - Path :" + path + ", URL =" + req.getRequestURL());
        if( path.contains("/public") ||
            path.equals("/") || path.isEmpty() || path.equals("/index.jsp") ||
            (path.equals("/login") && req.getMethod().toLowerCase().equals("post")))
            chain.doFilter(request, response);
        else
            res.sendRedirect("/");

        return;
    }
}

Code of Log.java: package FamilyTask.lib;

import ...
...
import java.util.*;
import java.util.logging.*;
import javax.naming.*;

public class Log
{
    private static Boolean isInit = false;
    private static Logger LOGGER = null;
    private static Handler handler = null;

    private static void Init()
    {
        if(isInit && LOGGER != null)
            return ;
    
        try 
        {
            handler = new FileHandler("debug_log");
            LOGGER.addHandler(handler);
            handler.setLevel(Level.ALL);
            handler.close();
        }
        catch(IOException exc)
        {
            System.out.println("Error: Couldn't create or open Log file. Error message: " +  exc.getMessage());
        }
        isInit = true;
    
        return;
    }

    public static void Info(String message)
    {
        if(!isInit)
            Log.Init();
    
        System.out.println("Info: " + message);
        LOGGER.info("Info: " + message);
    }

    public static void Error(String message)
    {
        if(!isInit)
            Log.Init();

        System.out.println("Error: " + message);
        LOGGER.warning("Error: " + message);
    }
}

Command for compile servlet/filter classes:

javac --release 8 -cp "D:\path\to\my\project\webapps\ROOT\WEB_INF\classes\";"D:\path\to\my\project\lib\servlet-api.jar" "<servlet or filter name>.java"

Command for compile simple classes:

javac --release 8 -cp "D:\path\to\my\project\webapps\ROOT\WEB_INF\classes\" "<class name>.java"

Compilation ends without errors, but on run time I'm getting this error:

Exception
    javax.servlet.ServletException: При выполнении фильтра выброшено исключение
Root Cause
    java.lang.NoClassDefFoundError: FamilyTask/lib/Log
    FamilyTask.filters.AccessFilter.doFilter(AccessFilter.java:42)
Root Cause
java.lang.ClassNotFoundException: FamilyTask.lib.Log
    org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1365)
    org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188)
    FamilyTask.filters.AccessFilter.doFilter(AccessFilter.java:42)
Questioner
Humoyun
Viewed
0
Humoyun 2020-12-07 19:32:54

I solved this problem. The reason is that from previous compilation left log.class file (first letter is exactly lowercase letter, not Log.class). On prev compilation log class name started from lowercase letter. On next compilations with uppercase letter names the file system replaced old log.class file with the same name file. Deleting old .class file solved the problem.