edit: добавлены @Repository и @Service к классам UserDAOImpl и UserServiceImpl в соответствии с предложениями user7294900 и @skhussain, однако я все еще получаю аналогичную трассировку стека (дополнено ниже)
Я создаювеб-приложение с Spring MVC с использованием Hibernate, REST и Maven.Я могу нормально добраться до своей страницы index.jsp, однако попытка достичь моего отображения REST дает мне следующую трассировку стека:
HTTP Status 500 – Internal Server Error
Type Exception Report
Message Servlet.init() for servlet [dispatcher] threw exception
Description The server encountered an unexpected condition that prevented it from fulfilling the request.
Exception
javax.servlet.ServletException: Servlet.init() for servlet [dispatcher] threw exception
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.base/java.lang.Thread.run(Thread.java:834)
Root Cause
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userDAOImpl': Unsatisfied dependency expressed through field 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in co.uk.nightmarengine.remixapp.config.AppConfig: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.hibernate.cfg.annotations.reflection.JPAMetadataProvider.<init>(Lorg/hibernate/boot/spi/BootstrapContext;)V
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846)
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:696)
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:574)
org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:526)
org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:169)
javax.servlet.GenericServlet.init(GenericServlet.java:158)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.base/java.lang.Thread.run(Thread.java:834)
У меня была похожая проблема, подобная этой, с проектом Spring MVC, и этотребуется обновить мои зависимости в pom.xml.Однако я чувствую, что я прошел через зависимости и кодировал миллион раз без всякой удачи!
/ remixapp / pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>co.uk.nightmarengine</groupId>
<artifactId>remixapp</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>remixapp Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<springframework.version>5.1.2.RELEASE</springframework.version>
<hibernate.version>5.3.7.Final</hibernate.version>
<mysql.connector.version>8.0.13</mysql.connector.version>
<c3po.version>0.9.5.2</c3po.version>
<springsecurity.version>5.1.1.RELEASE</springsecurity.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- Commons logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Jackson Project -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.5.6-Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
<!-- C3PO -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3po.version}</version>
</dependency>
<!-- Spring Security -->
<!-- spring-security-web and spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<!-- Servlet+JSP+JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
<build>
<finalName>spring-crm-rest</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
</plugin>
</plugins>
</build>
</project>
/ remixapp / src / main / java /co / uk / nightmarengine / remixapp / config / SpringMvcDispatcherServletInitializer.java:
package co.uk.nightmarengine.remixapp.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class SpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { AppConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
/ remixapp / src / main / java / co / uk / nightmarengine / remixapp / config / AppConfig.java
package co.uk.nightmarengine.remixapp.config;
import java.beans.PropertyVetoException;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import com.mchange.v2.c3p0.ComboPooledDataSource;
@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("co.uk.nightmarengine.remixapp")
@PropertySource({ "classpath:persistence-mysql.properties" })
public class AppConfig implements WebMvcConfigurer {
@Autowired
private Environment env;
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
@Bean
public DataSource myDataSource() {
ComboPooledDataSource myDataSource = new ComboPooledDataSource();
try {
myDataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
}
catch (PropertyVetoException exc) {
throw new RuntimeException(exc);
}
myDataSource.setJdbcUrl(env.getProperty("jdbc.url"));
myDataSource.setUser(env.getProperty("jdbc.user"));
myDataSource.setPassword(env.getProperty("jdbc.password"));
myDataSource.setInitialPoolSize(getIntProperty("connection.pool.initialPoolSize"));
myDataSource.setMinPoolSize(getIntProperty("connection.pool.minPoolSize"));
myDataSource.setMaxPoolSize(getIntProperty("connection.pool.maxPoolSize"));
myDataSource.setMaxIdleTime(getIntProperty("connection.pool.maxIdleTime"));
return myDataSource;
}
private Properties getHibernateProperties() {
Properties props = new Properties();
props.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
props.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
return props;
}
private int getIntProperty(String propName) {
String propVal = env.getProperty(propName);
int intPropVal = Integer.parseInt(propVal);
return intPropVal;
}
@Bean
public LocalSessionFactoryBean sessionFactory(){
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(myDataSource());
sessionFactory.setPackagesToScan(env.getProperty("hibernate.packagesToScan"));
sessionFactory.setHibernateProperties(getHibernateProperties());
return sessionFactory;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
}
/ remixapp / src / main / resources / persistence-mysql.properties:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/remix_webapp?useSSL=false&serverTimezone=UTC
jdbc.user=<username>
jdbc.password=<password>
connection.pool.initialPoolSize=5
connection.pool.minPoolSize=5
connection.pool.maxPoolSize=20
connection.pool.maxIdleTime=3000
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.packagesToScan=co.uk.nightmarengine.remixapp.entity
/ remixapp / src / main / java / co / uk / nightmarengine / remixapp / entity / User.java
package co.uk.nightmarengine.remixapp.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="User")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private int id;
@Column(name="username")
private String username;
@Column(name="password")
private String password;
@Column(name="enabled")
private int enabled;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
@Column(name="email")
private String email;
@Column(name="created_at")
private String createdAt;
@Column(name="location")
private String location;
@Column(name="description")
private String description;
@Column(name="picture_file")
private String pictureFile;
public User() {
}
public User(String username, String password, int enabled, String createdAt) {
this.username = username;
this.password = password;
this.enabled = enabled;
this.createdAt = createdAt;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getEnabled() {
return enabled;
}
public void setEnabled(int enabled) {
this.enabled = enabled;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPictureFile() {
return pictureFile;
}
public void setPictureFile(String pictureFile) {
this.pictureFile = pictureFile;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password
+ ", enabled=" + enabled + "]";
}
}
/ remixapp / src / main / java / co / uk / nightmarengine / remixapp / dao / UserDAOImpl.java:
package co.uk.nightmarengine.remixapp.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import co.uk.nightmarengine.remixapp.entity.User;
@Repository
public class UserDAOImpl implements UserDAO {
@Autowired
private SessionFactory sessionFactory;
@Override
public List<User> getUsers() {
Session currentSession = sessionFactory.getCurrentSession();
Query<User> query = currentSession.createQuery(
"from User", User.class);
List<User> users = query.getResultList();
return users;
}
@Override
public void saveUser(User user) {
// TODO Auto-generated method stub
}
@Override
public User getUser(int id) {
// TODO Auto-generated method stub
return null;
}
@Override
public void deleteUser(int id) {
// TODO Auto-generated method stub
}
}
/ remixapp / src / main / java /co / uk / nightmarengine / remixapp / service / UserServiceImpl.java:
package co.uk.nightmarengine.remixapp.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import co.uk.nightmarengine.remixapp.dao.UserDAO;
import co.uk.nightmarengine.remixapp.entity.User;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDAO userDAO;
@Override
public List<User> getUsers() {
return userDAO.getUsers();
}
@Override
public void saveUser(User user) {
// TODO Auto-generated method stub
}
@Override
public User getUser(int id) {
// TODO Auto-generated method stub
return null;
}
@Override
public void deleteUser(int id) {
// TODO Auto-generated method stub
}
}
/ remixapp / src / main / java / co / uk / nightmarengine / remixapp / rest / UserRestController.java:
package co.uk.nightmarengine.remixapp.rest;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import co.uk.nightmarengine.remixapp.entity.User;
import co.uk.nightmarengine.remixapp.service.UserService;
@RestController
@RequestMapping("/api")
public class UserRestController {
@Autowired
private UserService userService;
@GetMapping("/users")
public List<User> getUsers(){
return userService.getUsers();
}
}
/ remixapp / src / main / webapp / index.jsp:
<html>
<body>
<h2>Hello World!</h2>
<a href="${pageContext.request.contextPath}/api/users">Get All Users</a>
</body>
</html>
Кроме того, корень контекста всегда по умолчанию имеет значение «spring-crm-rest», даже если я изменяю его на «remixapp»в Пропеrties -> Настройки веб-проекта ..?Я не уверен, почему - 'spring-crm-rest' был предыдущим проектом, но эта строка нигде не объявлена в моем коде.
Имея это в виду, я могу достичь 'http://localhost:8080/spring-crm-rest/без каких-либо проблем (что указывает на index.jsp).Однако запрос 'http://localhost:8080/spring-crm-rest/api/users' дает мне вышеуказанную трассировку стека.Фактически, ввод чего-либо после пути корневого контекста вызывает у меня ту же ошибку, например: 'http://localhost:8080/spring-crm-rest/fghfg'
Я подтвердил, что мое приложение может подключаться к базе данных MySQL, однако это было через базовый сервлет, который не былчтение из моего pom.xml.Я также пытался очистить кэш от Tomcat, очистить мой проект, удалить зависимости из моего локального репозитория maven, обновить зависимости проекта maven -> на случай, если есть какая-то проблема с кешем.