Reputation: 117
I am using Spring MVC without Spring Boot.
I am trying to setup Spring DATA JPA Repository in java classes, no xml.
I did it as shown here. Item No. 3 https://www.baeldung.com/the-persistence-layer-with-spring-and-jpa
and does not want to work, I don’t know what’s the matter.
The logs contain the following message:
org.springframework.beans.factory.UnsatisfiedDependencyExcep tion: Error creating bean with name 'userServiceImpl': Unsatisfied dependency expressed through field 'userRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionExcept ion: No qualifying bean of type 'com.testjpaspring.repository.UserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(req uired=true)}
Place your project on github https://github.com/romanych2021/TestJpaSpring
UserRepository
package com.testjpaspring.repository;
import com.testjpaspring.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername (String username);
}
UserService
package com.testjpaspring.service;
import com.testjpaspring.model.User;
import org.springframework.stereotype.Service;
@Service
public interface UserService {
User findByUsername (String username);
}
UserServiceImpl
package com.testjpaspring.service;
import com.testjpaspring.model.User;
import com.testjpaspring.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
@Service
@Transactional
public class UserServiceImpl implements UserService{
@Autowired
UserRepository userRepository;
@Override
public User findByUsername(String username) {
return userRepository.findByUsername(username);
}
}
MyController
package com.testjpaspring.controller;
import com.testjpaspring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@Autowired
UserService userService;
@ResponseBody
@GetMapping(value = "/")
public String home () {
return userService.findByUsername("roma").getUsername();
}
}
RootConfig
package com.testjpaspring.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.sql.DataSource;
import java.util.Properties;
@EnableWebMvc
@Configuration
@EnableTransactionManagement
@ComponentScan({"com.testjpaspring.repository", "com.testjpaspring.service"})
public class RootConfig implements WebMvcConfigurer {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("com.testjpaspring.model");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/testjpaspring?serverTimezone=UTC&useSSL=false");
dataSource.setUsername( "root" );
dataSource.setPassword( "1234" );
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
return properties;
}
}
Config
package com.testjpaspring.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
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.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import java.util.Properties;
@Configuration
@EnableWebMvc
@ComponentScan({"com.testjpaspring.controller"})
public class Config implements WebMvcConfigurer{
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("/WEB-INF/templates");
configurer.setDefaultEncoding("UTF-8");
Properties properties = new Properties();
properties.setProperty("default_encoding", "UTF-8");
configurer.setFreemarkerSettings(properties);
return configurer;
}
@Bean
public ViewResolver getViewResolver(){
FreeMarkerViewResolver viewResolver = new FreeMarkerViewResolver();
viewResolver.setSuffix(".ftl");
viewResolver.setContentType("text/html;charset=UTF-8");
viewResolver.setCache(false);
return viewResolver;
}
}
POM.XML
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.testjpaspring</groupId>
<artifactId>TestJpaSpring</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${encoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<failOnMissingWebXml>false</failOnMissingWebXml>
<java.version>1.8</java.version>
<encoding>UTF-8</encoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>5.2.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Framework-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</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.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
<!-- Hibernate-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.4.21.Final</version>
</dependency>
<!-- Остальные-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
</dependencies>
</project>
Upvotes: 1
Views: 1539
Reputation: 4900
You are missing
@EnableJpaRepositories(basePackages = "com.testjpaspring.repository")
on your RootConfig
class.
As a matter of fact, the class should look like this:
@Configuration
@ComponentScan("com.testjpaspring.service")
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.testjpaspring.repository")
public class RootConfig {
// Keep method as are
}
It has nothing todo with your WebMVC Setup.
As I just realized that you found out yourself (didn't click the 5 more comments before), here's an explanation:
This is something normally done by Spring Boot these days. You need to explicitly specify the package name as the annotation processor would look down the package in which the annotated config class is in.
Without the annotation or the explicit package name, Spring Data JPA repositories are never bootstrapped and as such, not available in the context.
Adding @Repository
to them makes them Spring Beans IF you would have added that to a class. However, the UserRepository
is a declarative interface, not a class.
Also, you can remove @Repository
from the UserRepository
, this not needed for JPA Repositories to work.
Upvotes: 1