0

I'm trying to set up a Spring Boot/MySQL/docker project. After adding the repository classes, I started getting this error:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'filterController': Unsatisfied dependency expressed through field 'filterService': 
Error creating bean with name 'filterServiceImpl': Unsatisfied dependency expressed through field 'filterRepository': 
No qualifying bean of type 'backend.challenge.repositories.FilterRepository' available: 
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: 
{@org.springframework.beans.factory.annotation.Autowired(required=true)}

Checked my classes and this question, annotated everything. There are two repositories, I'll just post one:

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface FilterRepository extends JpaRepository<FilterEntity, String> {}

Service:

import org.springframework.stereotype.Service;

import java.util.List;

@Service
public interface FilterService {
    FilterResponseDto createFilter(FilterRequestDto filterRequestDto);
    List<FilterResponseDto> getAllFilters();
}

Service implementation:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class FilterServiceImpl implements FilterService{
    @Autowired
    private FilterRepository filterRepository;
    @Autowired
    private FilterChangelogRepository filterChangelogRepository;

    //method implementations here
}

Controller:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.util.List;

@RestController
@RequestMapping("filters")
@Validated
public class FilterController {
    @Autowired
    private FilterService filterService;
    //mappings here
}

application.properties (pointing to the MySQL db running on docker)

spring.datasource.url=jdbc:mysql://mysqldb:3306/challenge
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver

Lastly, my dependency list which is quite a mess:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>6.0.4</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>6.0.4</version>
    </dependency>
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.0.32</version>
    </dependency>
    <dependency>
        <groupId>javax.persistence</groupId>
        <artifactId>javax.persistence-api</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>2.1.4.RELEASE</version>
    </dependency>
</dependencies>

Would appreciate if anybody could share some thoughts on this.

Edit1: cleaned dependencies, still getting the same error.

Edit2: Adding docker-compose file:

services:

  yourapp:
    depends_on:
      - mysqldb
    restart: always
    build:
      context: ./
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    depends_on:
      mysqldb:
        condition: service_healthy
    environment:
      MYSQL_HOST: mysqldb
      MYSQL_USER: root
      MYSQL_PASSWORD: root
      MYSQL_PORT: 3306
    stdin_open: true
    tty: true

  mysqldb:
    image: mysql:8.0
    restart: always
    ports:
      - "3306:3306"
    environment:
      MYSQL_DATABASE: challenge
      MYSQL_ROOT_PASSWORD: root
    healthcheck:
            test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
            timeout: 30s
            retries: 5
invzbl3
  • 5,872
  • 9
  • 36
  • 76
user3641702
  • 393
  • 1
  • 5
  • 18
  • 1
    For what it's worth, some thoughts to think about. First, I find it a bit strange to have @Service on both the FilterService and FilterServiceImpl. I would only put it on the implementation class... Second, why so many dependencies like spring-tx, javax.transaction-api, javax.persistence, etc. Those should all be provided by the spring-data-jpa dependency. I recommend cleaning up those dependencies to exclude conflicting packages as a possible cause... I guess leaving the starters and mysql-connector should be sufficient... – KDW Feb 18 '23 at 20:20
  • @KDW javax.persistence, for instance, is for my Entity classes. I want to have some transactions, that's why I have spring-tx, javax.transaction-api. Is spring-data-jpa dependency enough for what I want to achieve? – user3641702 Feb 18 '23 at 20:36
  • Since you are using Spring Boot in your application, you only need to define the following dependencies for database access. tx, persintence, etc is part of the starter dependency. org.springframework.boot spring-boot-starter-data-jpa mysql mysql-connector-java runtime – KDW Feb 18 '23 at 20:49
  • Is the mentioned error message the entire stacktrace? Your db is running in Docker, is it accessible on the application.properties uri using e.g. MySQL Workbench? Does your application run in a Docker container as well, or does it run in your IDE? – KDW Feb 18 '23 at 21:00
  • This may be caused when the repository is not scanned - maybe your `@SpringBootApplication` class is in different package - to make it work, it has to be in the same or any parent package – dey Feb 18 '23 at 23:36
  • did you enable jpa repositories using @EnableJpaRepositories? – SputNick Feb 18 '23 at 23:45

2 Answers2

0

I think you can replace your dependencies with the following.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
</dependency>
<dependency>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-core</artifactId>
    <version>4.19.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

If you run your Spring Boot application inside your IDE or as a non-containerized application on the same host as your Docker engine, try using localhost instead of the container name.

spring.datasource.url=jdbc:mysql://localhost:3306/challenge
KDW
  • 485
  • 3
  • 17
  • Adding spring-boot-starter-data-jpa adds HikariCP and I'm getting a new error now: Caused by: org.hibernate.HibernateException: Unable to determine Dialect without JDBC metadata (please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect') Regarding docker, I've added my docker-compose in the original post. – user3641702 Feb 18 '23 at 21:54
  • Looks like a configuration issue/conflict. Would it be possible by any chance to share your code somewhere on a Git repository? – KDW Feb 19 '23 at 14:42
0

Upon much trial and error and after fixing my dependencies as @KDW suggested, I finally figured out what was wrong. I created my project from Spring Initializr with version 3.0.2. Turns out there are some issues as mentioned here and here. Also, I was missing some annotations on my main class. Here's my solution:

Step 1 - Downgrade Spring Boot version from 3.0.2 to 2.7.8:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.8</version>
    <relativePath/>
</parent>

Step 2 - Dependency list

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</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-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.32</version>
    </dependency>
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
    </dependency>
    <dependency>
        <groupId>javax.persistence</groupId>
        <artifactId>javax.persistence-api</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>2.1.4.RELEASE</version>
    </dependency>
</dependencies>

Step 3 - Annotations on main class

@ServletComponentScan
@EnableJpaRepositories("package_with_my_repositories")
@EntityScan("package_with_my_entities")
@SpringBootApplication
user3641702
  • 393
  • 1
  • 5
  • 18