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!
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.
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.
It means the server is unable to locate the class file. Just check the classpath.
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).
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:
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 NoClassDefFoundError
s 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With