问题
I am working on a Spring webapp using annotations and Hibernate. One of the goals here is that the application be annotation driven (instead of XML) for all elements of the stack, which right now is just spring and hibernate. Every solution from this and other questions I asked here about this code leads to a whack a mole style conflagration of issues, but this cant be that hard. Please try this code! It's much easier than us all going through a point by point exposition of stack traces.
A Github link is included, just git clone, maven clean package, and deploy to a suitable server such as Jetty, you can see all these traces in action.
Here is how this started: when firing up a webapp I got the following no class def found error:
java.lang.noclassdeffounderror L[org.hibernate.engine.FilterDefinition
I am using Hibernate 4.3.4
<hibernate.version>4.3.4.Final</hibernate.version>
and am using the core jar
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
Here was the trace
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.mobiusinversion.web.repositories.UserRepository com.mobiusinversion.web.services.UserService.userRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory com.mobiusinversion.web.repositories.UserRepository.sessionFactory; nested exception is java.lang.NoClassDefFoundError: [Lorg/hibernate/engine/FilterDefinition;
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:530)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:244)
Now searching maven central, I see that class is in Hibernate 3.1, so now I've added that to my pom
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate4.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>${hibernate3.version}</version>
</dependency>
Along with the following required repository (which was a undocumented requirement, GROWL)
<repositories>
<repository>
<id>java.net</id>
<url>http://download.java.net/maven/2/</url>
</repository>
</repositories>
However this leads to the following trace
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.mobiusinversion.web.repositories.UserRepository com.mobiusinversion.web.services.UserService.userRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory com.mobiusinversion.web.repositories.UserRepository.sessionFactory; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getSessionFactory' defined in class com.mobiusinversion.web.spring.Config: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:530)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
Which after a number of stack traces contains
Caused by:
java.lang.ClassCastException: org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider cannot be cast to org.hibernate.engine.jdbc.connections.spi.ConnectionProvider
at org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.instantiateExplicitConnectionProvider(ConnectionProviderInitiator.java:194)
at org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.initiateService(ConnectionProviderInitiator.java:120)
at org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.initiateService(ConnectionProviderInitiator.java:55)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:83)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:223)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:197)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:178)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(JdbcServicesImpl.java:260)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:94)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:89)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:206)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:178)
at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1885)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1843)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1928)
Since there is a lot going on here, and Stack traces get long, please, I ask you to try this code for yourself when looking at a possible solution. The code is simple, self contained, and only requires maven and a suitable server.
https://github.com/mobiusinversion/SpringMVCWebApp
Help getting this working would be greatly appreciated. It just seems like every solution to ever stack trace leads to another in whack a mole fashion. Lets recap what we are try to do here:
Annotation based spring bean configuration Annotation based hibernate configuration
Should be simple, right?
[UPDATE 4/4/14 4pm] The issue is now a HibernateException casue by no session bound to thread:
Caused by:
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:106)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
at com.mobiusinversion.web.repositories.UserRepository.createUser(UserRepository.java:26)
at com.mobiusinversion.web.services.UserService.createUser(UserService.java:21)
at com.mobiusinversion.web.controllers.BasicController.createUser(BasicController.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:690)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:717)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1644)
at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:164)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1615)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:550)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:568)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1110)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:479)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:183)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1044)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:199)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:459)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:281)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:232)
at org.eclipse.jetty.io.AbstractConnection$1.run(AbstractConnection.java:505)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:607)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:536)
at java.lang.Thread.run(Thread.java:744)
After incorporating several good pieces of advice, here is the session bean construction in the spring config:
@Bean
public LocalSessionFactoryBean getSessionFactory() {
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
localSessionFactoryBean.setDataSource(getDataSource());
localSessionFactoryBean.setHibernateProperties(getHibernateProperties());
localSessionFactoryBean.setPackagesToScan("com.mobiusinversion.web");
return localSessionFactoryBean;
}
And here is where the error occurs.
@Transactional
@Repository
public class UserRepository {
@Autowired
private SessionFactory sessionFactory;
@SuppressWarnings("unchecked")
public Integer createUser(User user) {
User mergedUser = (User) sessionFactory.getCurrentSession().merge(user);
return mergedUser.getId();
}
}
回答1:
Based on this command line overlapping jars report (a tool I made), there are two hibernate versions in WEB-INF/lib of the WAR:
>>>> Jar overlap report:
hibernate-3.1.jar overlaps with hibernate-core-4.3.4.Final.jar -
total overlapping classes: 494
jboss-transaction-api_1.2_spec-1.0.0.Final.jar overlaps with jta-1.0.1B.jar -
total overlapping classes: 17
Total number of classes with more than one version: 511
Looking further in the POM with mvn dependency:tree we can see where the duplicates come from:
[INFO] +- org.hibernate:hibernate-core:jar:4.3.4.Final:compile
...
[INFO] +- org.hibernate:hibernate:jar:3.1:compile
In this case there are two versions of hibernate added in the classpath, as hibernate is declared twice with different artifact names. The solution for this is to choose only one version of Hibernate, removing the other from the POM. The best would be to choose 4.3.4.Final because 3.1 is very ancient.
回答2:
java.lang.noclassdeffounderror L[org.hibernate.engine.FilterDefinition
is most likely because hibernate jar is missing from your classpath. Typically this happen if you forget to declare hibernate dependency on your maven pom.
To be able to inject HibernateSession, one simple way is to create LocalSessionFactoryBean and autowire it to your class.
However some java container already has its own HibernateSessionFactory and this method might not be suitable.
回答3:
Maybe you have 2 different jars of Hibernate Or you have to configure the servlet container in order to use the web app classloader as first class loader Moreover if I'm not wrong hibernate 4.3.X supports JPA2.1 spec so you should use this spec
Angelo
来源:https://stackoverflow.com/questions/22750449/spring-webapp-with-hibernate-annotation-driven-issue-after-issue-source-code