I want to make an AngularJS + Spring MVC + Hibernate + MySQL application. And I can't understand how to configure spring beans, so that I will be able to use @Autowired
annotations to my repository and entity classes.
pom.xml
dependencies:
<groupId>com.kspt</groupId>
<artifactId>pms</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<java-version>1.8</java-version>
<spring-core.version>4.1.6.RELEASE</spring-core.version>
<javax.servlet-api.version>3.1.0</javax.servlet-api.version>
<spring-data-jpa.version>1.9.2.RELEASE</spring-data-jpa.version>
<hibernate.version>5.2.12.Final</hibernate.version>
<mysql-connector-java.version>5.1.34</mysql-connector-java.version>
<commons-dbcp2.version>2.1.1</commons-dbcp2.version>
<jta.version>1.1</jta.version>
<junit.version>4.11</junit.version>
<spring-webmvc.version>4.1.6.RELEASE</spring-webmvc.version>
<spring-test.version>4.1.6.RELEASE</spring-test.version>
<jstl.version>1.2</jstl.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-core.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-core.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-webmvc.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-webmvc.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet-api.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring-data-jpa.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency>
<!--JSF (include "jsf-api" and "jsf-impl")-->
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.2.10</version>
</dependency>
</dependencies>
User
entity class:
@Entity
@Table(name = "USERS")
public class User {
@Id
@Column(name = "ID")
@GeneratedValue
private Long id;
@Column(name = "LOGIN", unique = true, nullable = false)
private String login;
@Column(name = "NAME")
private String name;
@JsonIgnore
@Column(name = "PASSWORD")
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Repository for User
:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByLogin(String login);
}
Controller for User
:
@RestController
@RequestMapping({"{login}"})
public class UserController {
@Autowired
UserRepository userRepository;
@RequestMapping
public User getUser(@PathVariable String login) {
return userRepository.findByLogin(login)
.orElseThrow(() -> new UserNotFoundException(login));
}
@RequestMapping(method = RequestMethod.POST)
public void addUser(@PathVariable String login, @RequestBody User user) {
userRepository.save(user);
}
}
Configuration class:
@EnableWebMvc
@Configuration
@ComponentScan("com.kspt.pms")
public class AppConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/WEB-INF/resources/");
}
@Bean
public ViewResolver getViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/view/");
resolver.setSuffix(".jsp");
return resolver;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
com.kspt.pms.AppConfig
</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping>
</web-app>
When I try to run application, I get following exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.kspt.pms.repository.UserRepository com.kspt.pms.controller.UserController.userRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.kspt.pms.repository.UserRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
As I understood, this happens because I have not created an applicationContext.xml
file for Spring to know how to autowire all bean classes. I decided to try @EnableAutoConfiguration
annotation, so that it will automaticly generate all required files. But when I add that annotation to AppConfig
class, I get following error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean]: Factory method 'entityManagerFactory' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] is defined
So I have several questions:
Am I right that I need to create applicationContext.xml
file with beans description, or when you use Hibernate (or Spring Data) it can somehow generate this file automatically somehow?
Is there any other way no to write applicationContext
manually, but to generate it somehow?
If I'm wrong about applicationContext
, then why I have these errors?
And maybe I'm just don't understand the concept of Spring and Hybernate properly. So can anyone help me please?
No qualifying bean of type [javax.sql.DataSource] is defined
That's the key of your problem. To support repositories and hibernate you need to declare DataSource bean with all the configs of your DB - URL, credentials etc.
See here for annotated DataSource config example or for XML based config here
You need something like this
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getRequiredProperty("jdbc.url"));
dataSource.setUsername(env.getRequiredProperty("jdbc.username"));
dataSource.setPassword(env.getRequiredProperty("jdbc.password"));
return dataSource;
}
What worked for me:
I used IO Spring Platform for resolving dependencies and spring library versions in pom.xml
:
<groupId>com.kspt</groupId> <artifactId>pms</artifactId> <version>1.0-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <properties> <java-version>1.8</java-version> <spring-core.version>4.1.6.RELEASE</spring-core.version> <javax.servlet-api.version>3.1.0</javax.servlet-api.version> <spring-data-jpa.version>1.9.2.RELEASE</spring-data-jpa.version> <hibernate.version>5.2.12.Final</hibernate.version> <mysql-connector-java.version>5.1.34</mysql-connector-java.version> <commons-dbcp2.version>2.1.1</commons-dbcp2.version> <jta.version>1.1</jta.version> <junit.version>4.11</junit.version> <spring-webmvc.version>4.1.6.RELEASE</spring-webmvc.version> <spring-test.version>4.1.6.RELEASE</spring-test.version> <jstl.version>1.2</jstl.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>io.spring.platform</groupId> <artifactId>platform-bom</artifactId> <version>Brussels-SR6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.5.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.5.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.5.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${javax.servlet-api.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-connector-java.version}</version> </dependency> <!--JSF (include "jsf-api" and "jsf-impl")--> <dependency> <groupId>org.glassfish</groupId> <artifactId>javax.faces</artifactId> <version>2.2.10</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> <!-- or use LATEST --> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.21</version> <!-- or use LATEST --> </dependency> </dependencies>
Added EntityManager, TransactionManager and DataSource beans to my config:
@Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName(env.getRequiredProperty("jdbc.driverClassName")); dataSource.setUrl(env.getRequiredProperty("jdbc.url")); dataSource.setUsername(env.getRequiredProperty("jdbc.username")); dataSource.setPassword(env.getRequiredProperty("jdbc.password")); return dataSource; } @Bean public JdbcTemplate jdbcTemplate(DataSource dataSource) { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.setResultsMapCaseInsensitive(true); return jdbcTemplate; } @Bean public EntityManagerFactory entityManagerFactory() { HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); vendorAdapter.setGenerateDdl(true); LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(vendorAdapter); factory.setPackagesToScan("com.kspt.pms"); factory.setDataSource(dataSource()); factory.setPersistenceUnitName("my-pms"); factory.setPersistenceProviderClass(HibernatePersistenceProvider.class); factory.afterPropertiesSet(); return factory.getObject(); } @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(entityManagerFactory()); return txManager; }
Added persistence.xml
file to resources/META-INF
and declared my persistance unit in it:
<persistence-unit name="my-pms"> <class>com.kspt.pms.entity.BugReport</class> <class>com.kspt.pms.entity.Comment</class> <class>com.kspt.pms.entity.Message</class> <class>com.kspt.pms.entity.Milestone</class> <class>com.kspt.pms.entity.Project</class> <class>com.kspt.pms.entity.Ticket</class> <class>com.kspt.pms.entity.User</class> </persistence-unit>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.