Spring: java.lang.NoClassDefFoundError: failed to initialize class

I am developing a small web application in Spring MVC. I get an exception every time I try to get my custom class in any controller if that class is using another custom class. This is easier to show with an example:

Controller where I am trying to get an object of custom WireTest class:

@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 always arises, no matter if I create the object directly or use @Autowired. In the code here, I'm showing @Autowired's case, 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 the class DBhelper.java

(there are other static members too, full code 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 can also use these classes without any problem in a console application, so it works outside of Spring.

My Spring config:

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 am using Maven to build and Tomcat 7 as a server if that matters. Spring version 4.0.1.RELEASE

Update: full 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!

+3


source to share


2 answers


Try lazy loading your factory session rather than initializing it statically by assigning a field final

.

For example, create a method like the following that returns a factory session, creating one if necessary. Whenever you want to use a factory session, call this method instead of accessing the field directly:

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

      

Personally, I don't like static initialization for anything non-trivial since you have no control over when it happens. With the above method, you control: the factory session is created on first use.

If you want to know what the problem is, I have two suggestions. First, reload the web app container and make sure you get the exception for the first time. (The "first time" is important here: Could not initialize class

means that the JVM has already tried and could not initialize the class.) Second, try wrapping the contents of the method createSessionFactory

in a block try

- catch

for example:

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

      



However, I cannot guarantee that any approach will offer you much enlightenment.

EDIT : Instead of just speculating, I decided to try this and see what happens. So I kicked out a small web application with Spring and Hibernate and deployed to Tomcat. While trying to get it working, I ran into several issues while trying to read the Hibernate config caused by me doing the following errors:

  • I have not included the hibernate.cfg.xml file in the .war file,
  • I have not included the database JAR driver in the .war file,
  • The database I was trying to connect to is not working.

In every case, my first approach worked. The first request made after restarting Tomcat gave me ExceptionInInitializerError

further details below. The second and subsequent queries gave me NoClassDefFoundError

that didn't tell me about the problem.

The problem is that after a class has ExceptionInInitializerError

been thrown for a class, the JVM will blacklist that class and subsequently refuse to do anything with it. This way, you only get one chance to see what is wrong in the static initialization code. If you initialize Hibernate lazily as I recommended above, you will get a detailed exception message every time. Consider this one more reason to avoid static initialization.

+4


source


Check static initialization DBhelper

.

"NoClassDefFoundError: Could not initialize class" error



In this case, instantiate sessionFactory

as a spring bean and build the spring container with DBhelper

.

0


source







All Articles