Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring: java.lang.NoClassDefFoundError: Could not initialize class

I am developing a little web application in Spring MVC. I get the exception every time I try to get my custom class in any controller, in case if this class uses another custom class. It is easier to show on example:

Controller, where I'm trying to get an object of custom class WireTest:

@Controller
@RequestMapping("/offices")
public class OfficesController {

  @Autowired
  private WireTest wt;

  @RequestMapping("")
  public String offices(Model model) {
    model.addAttribute("test", wt.getString());
    return "offices";
  }
}

The problem happens always, whether I'm creating an object directly or use @Autowired. In code here, I'm showing the case of @Autowired, but that doesn't matter - I could write private WireTest wt = new WireTest(), and the exception would be the same.

WireTest.java class:

@Service
public class WireTest {
  public String getString() {return (DBhelper.getString());}
}

Part of DBhelper.java class (There are also other static members, the full code is below):

public class DBhelper {
    public static String getString() {return "Hi!";}
}

And the exception:

HTTP Status 500 - Handler processing failed; nested exception is         
java.lang.NoClassDefFoundError: Could not initialize class org.sher.wtpractice.dao.DBhelper

I also can use these classes without any problems in console application, so it works outside Spring.

My Spring configuration:

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <!-- Processes application requests -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
</web-app>

dispatcher-servlet.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

<context:component-scan base-package="org.sher.wtpractice.spring, org.sher.wtpractice.dao" />
    <mvc:annotation-driven />
    <mvc:resources mapping="/css/**" location="/css/"/>
    <mvc:resources mapping="/js/**" location="/js/"/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
</beans>

I'm using Maven for building and Tomcat 7 as a server, if that matters. Spring version is 4.0.1.RELEASE

Update: Complete code of DBhelper.java

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

import java.util.Calendar;
import java.util.Date;
public class DBhelper {
    private static final SessionFactory sessionFactory = createSessionFactory();

    private static SessionFactory createSessionFactory() {
        Configuration configuration = new Configuration();
        configuration.configure();
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
                configuration.getProperties()).build();
        return configuration.buildSessionFactory(serviceRegistry);
    }

    public static Object queryWrapper(DBoperation op) {
        Session session = sessionFactory.openSession();
        Transaction transaction = null;
        Object result = null;
        try {
            transaction = session.beginTransaction();
            result = op.operation(session);
            session.getTransaction().commit();
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
//            throw e;
        } finally {
            if (session != null && session.isOpen())
                session.close();
        }
        return result;
    }
    public static Date normalizeCal(Calendar cal) {
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }
    public static String getString() {return "Hi!";}
}

Any help would be greatly appreciated!

like image 558
ars Avatar asked Sep 06 '14 14:09

ars


People also ask

Could not initialize the class caused by Java Lang NoClassDefFoundError?

There could be multiple reasons like: 1) The class is not available in Java Classpath. 2) You might be running your program using the jar command and class was not defined in the manifest file's ClassPath attribute. 3) Any start-up script is an overriding Classpath environment variable.

How do I fix Java Lang NoClassDefFoundError?

lang. NoClassDefFoundError, which means the Class Loader file responsible for dynamically loading classes can not find the . class file. So to remove this error, you should set your classpath to the location where your Class Loader is present.

Could not initialise class error in java?

It means the server is unable to locate the class file. Just check the classpath.

Could not initialize class meaning?

lang. noclassdeffounderror: could not initialize class error by our server means it cannot locate the class file. It can be caused by different reasons that are listed below. The issue can be in the static block (also called a static initializer).


1 Answers

Try lazy-loading the session factory instead of initializing it statically by assigning to a final field.

For example, create a method such as the following, which returns the session factory, creating it if necessary. Whenever you want to use the session factory, call this method instead of referring directly to the field:

private static SessionFactory getSessionFactory() {
    if (sessionFactory == null) {
        sessionFactory = createSessionFactory();
    }
    return sessionFactory;
}

Personally I dislike static initialization for anything non-trivial, as you're out of control of when it happens. With the above method you are in control: the session factory gets created the first time you need to use it.

If you want to know what the problem is, I have two suggestions. Firstly, restart your web application container and see if you get a different exception message first time. (The 'first time' is important here: Could not initialize class means that the JVM has already tried and failed to initialize the class.) Secondly, try wrapping the contents of the createSessionFactory method in a try-catch block such as the following:

try {
    ...
} catch (Throwable e) {
    e.printStackTrace();
    throw new RuntimeException(e);
}

However, I can't guarantee that either approach will offer you much enlightenment.

EDIT: rather than just speculate, I decided to actually try this out and see what happens. So I knocked up a small web application using Spring and Hibernate and deployed it to Tomcat. While attempting to get it working I encountered a few issues when attempting to read the Hibernate configuration, caused by me making the following mistakes:

  • I hadn't included the hibernate.cfg.xml file in the .war file,
  • I hadn't included the database's JDBC driver JAR in the .war file,
  • the database I was trying to connect to was down.

In each case my first approach worked. The first request made following a Tomcat restart gave me an ExceptionInInitializerError with further details below it. The second and subsequent requests gave me NoClassDefFoundErrors which didn't tell me much about the problem.

The problem is that once an ExceptionInInitializerError has been thrown for a class, the JVM blacklists this class and will refuse to do anything with it subsequently. So you only get one chance to see what goes wrong in static initialization code. If you initialized Hibernate lazily as I recommended above, you would get the detailed exception message every time. Consider this another reason to avoid static initialization.

like image 155
Luke Woodward Avatar answered Nov 04 '22 00:11

Luke Woodward