javaspring-bootmavencrud-repository

Java Spring Boot MySQL - Spring Dependency Injection Failing


I'm working on a sample java spring boot REST service that need to be connected to local mysql instance. To start with I'm trying to get all records from MySQL local DB table. While starting the spring boot application, I'm getting below error.

2024-01-05T12:58:42.477-05:00\[0;39m \[33m WARN\[0;39m \[35m18340\[0;39m \[2m---\[0;39m \[2m\[           main\]\[0;39m \[36mConfigServletWebServerApplicationContext\[0;39m \[2m:\[0;39m Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'controller': Unsatisfied dependency expressed through field 'usersService': Error creating bean with name 'usersServiceImpl': Unsatisfied dependency expressed through field 'userRepository': No qualifying bean of type 'com.poc.sql.UserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
\[2m2024-01-05T12:58:42.478-05:00\[0;39m \[32m INFO\[0;39m \[35m18340\[0;39m \[2m---\[0;39m \[2m\[           main\]\[0;39m \[36mo.apache.catalina.core.StandardService  \[0;39m \[2m:\[0;39m Stopping service \[Tomcat\]
\[2m2024-01-05T12:58:42.487-05:00\[0;39m \[32m INFO\[0;39m \[35m18340\[0;39m \[2m---\[0;39m \[2m\[           main\]\[0;39m \[36m.s.b.a.l.ConditionEvaluationReportLogger\[0;39m \[2m:\[0;39m

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
\[2m2024-01-05T12:58:42.493-05:00\[0;39m \[31mERROR\[0;39m \[35m18340\[0;39m \[2m---\[0;39m \[2m\[           main\]\[0;39m \[36mo.s.b.d.LoggingFailureAnalysisReporter  \[0;39m \[2m:\[0;39m

***************************

APPLICATION FAILED TO START

***************************

Description:

Field userRepository in com.poc.sql.UsersServiceImpl required a bean of type 'com.poc.sql.UserRepository' that could not be found.

The injection point has the following annotations:
\- @org.springframework.beans.factory.annotation.Autowired(required=true)

Action:

Consider defining a bean of type 'com.poc.sql.UserRepository' in your configuration.

Here is the sample code snippet

Main Class



package com.poc.sql;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan({"com.poc.sql"})
public class MySqlPocApplication {

    public static void main(String[] args) {
        SpringApplication.run(MySqlPocApplication.class, args);
    }

}

Controller Class

package com.poc.sql;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;



@RestController
@RequestMapping("/oms/sql/poc")
public class Controller {
    
    private static final Logger logger = LoggerFactory.getLogger(Controller.class);
    
    @Autowired
    private UsersService usersService;
    
    
    @RequestMapping(value = "/getAll", method = RequestMethod.GET, 
            produces = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody Iterable<Users> getAllRecords(){

        logger.info("Inside getAllRecords");
        
        return usersService.getAll();

    }

}

Entity Class

package com.poc.sql;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import org.apache.commons.lang3.builder.ToStringBuilder;

@Entity
public class Users {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String name;
    private int age;
    private String department;
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
    
    @Override
    public String toString() {
        ToStringBuilder builder = new ToStringBuilder(this);
        builder.append("Users [id=");
        builder.append(id);
        builder.append(", name=");
        builder.append(name);
        builder.append(", age=");
        builder.append(age);
        builder.append(", department=");
        builder.append(department);
        builder.append("]");
        return builder.toString();
    }
    
    

}

Repository Class

package com.poc.sql;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends CrudRepository<Users, Integer> {

}

Interface and Service Classes

package com.poc.sql;

import java.util.List;


public interface UsersService {
    
    public List<Users> getAll();

}
package com.poc.sql;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UsersServiceImpl implements UsersService {

    @Autowired
    private UserRepository userRepository;
    
    @Override
    public List<Users> getAll() {
        
        return (List<Users>) userRepository.findAll();
        
    }

}

POM File

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.poc.sql</groupId>
    <artifactId>mysql-poc</artifactId>
    <version>${revision}</version>
    <name>mysql-poc</name>
    <description>mysql-poc</description>

    <properties>
        <java.version>17</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <revision>0.0.1-SNAPSHOT</revision>
        <spring-cloud.version>2022.0.1</spring-cloud.version>
        <maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
            <version>2.0.2.RELEASE</version><!--$NO-MVN-MAN-VER$-->
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>javax.persistence-api</artifactId>
            <version>2.2</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>

        <pluginManagement>
            <plugins>
                <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>
                                            org.apache.maven.plugins
                                        </groupId>
                                        <artifactId>
                                            maven-compiler-plugin
                                        </artifactId>
                                        <versionRange>
                                            [3.7.0,)
                                        </versionRange>
                                        <goals>
                                            <goal>testCompile</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>

    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>


</project>

I tried switching between CrudRepository and JpaRepository, adding @EnableJpaRepositories and none of them worked.

Can someone please check above code snippets and let me know what I'm missing here.

Also here are my configs from application.yaml file

spring:
jpa:
hibernate:
ddl-auto: update
datasource:
url: jdbc:mysql://${MYSQL_HOST:localhost}:3306/test
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver

Solution

  • From what I've observed in your implementation(controller and repository layer) aiming to create an API for getting user records, I think you shouldn't use spring-boot-starter-data-rest. Instead, you should use the dependencies listed below.

        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
          <!--MySQL driver-->
          <groupId>com.mysql</groupId>
          <artifactId>mysql-connector-j</artifactId>
          <scope>runtime</scope>
        </dependency>
    

    And you should remove this dependency also: (for spring boot 3, switch from javax.persistence to jakarta.persistence for handling data persistence)

        <dependency>
          <groupId>javax.persistence</groupId>
          <artifactId>javax.persistence-api</artifactId>
          <version>2.2</version>
        </dependency>
    

    So the import lines for entity class would be like this:

    import jakarta.persistence.Entity;
    import jakarta.persistence.GeneratedValue;
    import jakarta.persistence.GenerationType;
    import jakarta.persistence.Id;
    

    However, if you want to use spring-boot-starter-data-rest for API creation from spring data repositories I think you need to check more the way to implement stuff(like using @RepositoryRestResource), which is different way from above code.