1
votes

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>
1
That is a warning and not an error. So I assume everything else works?Jens Schauder
No, it does not work.zvzvzxvzxv
The link you gave me does not help solve the problem.zvzvzxvzxv
Shows not only warning, but also does not work.zvzvzxvzxv

1 Answers

1
votes

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.