Java 1.5 war in Tomcat7 producing InvokerServlet exception?

3.3k Views Asked by At

Hi..I have deployed my.war in Tomacat5.x, in that i was used java1.5 .At that time JAVA_HOME=java5path and CATALINA_HOME=tomcat5.x path in CentOS. It was working good.

Now my problem is,

I'm deploying the same war in Tomcat7.x with JAVA_HOME=java1.7 and CATALINE_HOME=tomcat7.x i'm getting the following error

java.lang.ClassNotFoundException: org.apache.catalina.servlets.InvokerServlet
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)...

As well i have compiled code in java1.7 too and deployed in Tomcat7..same error.Can any one suggest me how to overcome this problem ??

Thanks.

3

There are 3 best solutions below

1
On

I think tomcat 7 , support version 1.6 and up .

see here : http://tomcat.apache.org/whichversion.html

0
On

As of Tomcat 7 supports new Servlet standard version 3.0, we have to register all the servlet classes used inside.This strict for security purpose.

Tomcat 6 and below, web.xml

<servlet>
    <servlet-name>invoker</servlet-name>
    <servlet-class>
      org.apache.catalina.servlets.InvokerServlet
    </servlet-class>
    <init-param>
        <param-name>debug</param-name>
        <param-value>0</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>invoker</servlet-name>
    <url-pattern>/servlet/*</url-pattern>
</servlet-mapping>

Tomcat 7 and above

<listener>
    <listener-class>
        com.test.MyServletContextListener
    </listener-class>
</listener>
<context-param>
    <param-name>com.package</param-name>
    <param-value>
        com.test.servlet,
        com.example.application,
     </param-value>
    <description>servlet implemented packages</description>
</context-param>

In MyServletContextListener.java extends ServletContextListener and take all the classes and register using (override) contextInitialized method, like sample snippets below.

for (Class clazz : classes) {
        String mapping = prefix + clazz.getName();
        ServletRegistration sr = sc.addServlet(clazz.getName(), clazz.getName());
        sr.addMapping(mapping);
    }
0
On

I faced this issue while migrating from Tomcat 6 to Tomcat 7. Ricky over-here, improved on a solution, that almost worked for me. I had to improve it to work for me. I changed his Listener little bet and it worked like a charm. I hope it helps others:

    
    import java.io.File;
    import java.io.IOException;
    import java.net.JarURLConnection;
    import java.net.URL;
    import java.util.Enumeration;
    import java.util.HashSet;
    import java.util.Set;
    import java.util.jar.JarEntry;
    import java.util.jar.JarFile;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.ServletRegistration;
    import javax.servlet.http.HttpServlet;
    import org.apache.catalina.ContainerServlet;

    /**
     *
     * http://snippets.dzone.com/posts/show/4831
     * 
     * @author ricky
     */
    public class InvokerLoadListener implements ServletContextListener {

        /**
         * Invoker parameter that defines the packages to search servlets.
         * Comma separated list of packages
         */
        public static final String PACKAGES_PARAMETER = "invoker.packages";
        
        /**
         * Invoker parameter to setup the mapping name. By default is "/servlet/"
         */
        public static final String INVOKER_PREFIX_PARAMETER = "invoker.prefix";

        /**
         * Scans all classes accessible from the context class loader which 
         * belong to the given package and subpackages.
         * 
         * @param packageName
         * @return The list of classes found
         */
        private Set getClasses(String packageName) {
            Set classes = new HashSet();
            try {
                ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                String path = packageName.replace('.', '/');
                Enumeration resources = classLoader.getResources(path);
                while (resources.hasMoreElements()) {
                    URL resource = resources.nextElement();
                    if (resource.getProtocol().equals("jar")) {
                        // inside a jar => read the jar files and check
                        findClassesJar(resource, path, classes);
                    } else if (resource.getProtocol().equals("file")) {
                        // read subdirectories and find
                        findClassesFile(new File(resource.getFile()), packageName, classes);
                    } else {
                        System.err.println("Unknown protocol connection: " + resource);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return classes;
        }

        /**
         * Reads a jar file and checks all the classes inside it with the package
         * name specified.
         * 
         * @param resource The resource url
         * @param path
         * @param classes
         * @return 
         */
        private Set findClassesJar(URL resource, String path, Set classes) {
            JarURLConnection jarConn = null;
            JarFile jar = null;
            try {
                jarConn = (JarURLConnection) resource.openConnection();
                jar = jarConn.getJarFile();
                Enumeration e = jar.entries();
                while (e.hasMoreElements()) {
                    JarEntry entry = e.nextElement();
                    if ((entry.getName().startsWith(path + "/")
                            || entry.getName().startsWith(path + "."))
                            && entry.getName().endsWith(".class")) {
                        String name = entry.getName().replace('/', '.');
                        name = name.substring(0, name.length() - 6);
                        checkClass(name, classes);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    jar.close();
                } catch (IOException e) {
                }
            }
            return classes;
        }

        /**
         * Recursive method used to find all classes in a given file (file
         * or directory).
         *
         * @param file   The base directory
         * @param packageName The package name for classes found inside the base directory
         * @ classes The list of classes
         * @return The same classes
         * @throws ClassNotFoundException
         */
        private Set findClassesFile(File file, String packageName, Set classes) {
            if (file.isFile() && file.getName().endsWith(".class")) {
                //classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
                checkClass(packageName.substring(0, packageName.length() - 6), classes);
            } else {
                File[] files = file.listFiles();
                if ( files != null ){
                    for (File f : files) {
                        findClassesFile(f, packageName + "." + f.getName(), classes);
                    }
                }
            }
            return classes;
        }

        private Set checkClass(String name, Set classes) {
            try {
                Class clazz = Class.forName(name);
                //Changed the AND to an OR
                if (HttpServlet.class.isAssignableFrom(clazz)
                        || ContainerServlet.class.isAssignableFrom(clazz)) {
                    classes.add(clazz);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return classes;
        }

        @Override
        public void contextInitialized(ServletContextEvent sce) {
            System.out.println("contextInitialized(ServletContextEvent e)");
            ServletContext sc = sce.getServletContext();
            String list = sc.getInitParameter(PACKAGES_PARAMETER);
            String prefix = sc.getInitParameter(INVOKER_PREFIX_PARAMETER);
            if (prefix == null) {
                prefix = "/servlet/";
            }
            if (list != null) {
                String[] packages = list.split(",");
                for (int i = 0; i  0) {
                        System.out.println("Checking package: " + packageName);
                        // load classes under servlet.invoker
                        Set classes = getClasses(packageName);
                        System.out.println("size: " + classes.size());
                        for (Class clazz : classes) {
                            String mapping = prefix + clazz.getName();
                            System.out.println("Adding '" + clazz.getName() + "' in mapping '" + mapping + "'");
                            ServletRegistration sr = sc.getServletRegistration(clazz.getName());
                            //Changed this; it seems sometime the servlets are already registered, and needs remapping
                            if ( sr == null )
                                 sr = sc.addServlet(clazz.getName(), clazz.getName());
                            if ( sr != null )
                               sr.addMapping(mapping);
                        }
                    }
                }
            }
        }

        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            System.out.println("contextDestroyed(ServletContextEvent e)");
        }
    }

Cheers