0

Have sandbox springboot app. Decided to try reactive approach, postgres is used as database, I added r2dbc to the project to make my repository reactive. Here is my code:

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

@Repository
public interface ToDoRepository extends 
            ReactiveCrudRepository<ToDo,String> {
}

@RestController
@RequestMapping("/api/v1")
public class ToDoController {
    private final ToDoRepository repository;
    public ToDoController(ToDoRepository repository) {
        this.repository = repository;
    }

    @GetMapping(value = "/to-do", produces = {
            MediaType.APPLICATION_JSON_VALUE, 
            MediaType.APPLICATION_XML_VALUE, 
            MediaType.TEXT_XML_VALUE})
    public ResponseEntity<Flux<ToDo>> getToDos(@RequestHeader 
                                          HttpHeaders headers){
        return ResponseEntity.ok().body(repository.findAll());
    }
}

@Data
@RequiredArgsConstructor
@Entity
@Table(name = "todo")
public class ToDo {
    @Id
    @NotNull
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    private String id;
    @NotNull
    @NotBlank
    private String description;
    @CreationTimestamp
    private Timestamp created;
    @UpdateTimestamp
    private Timestamp modified;
    private boolean completed;
}

r2dbc config:

@Configuration
@EnableR2dbcRepositories(basePackages = 
   "com.springboot2.repository")
public class R2DBCConfig extends AbstractR2dbcConfiguration {
@Bean
public ConnectionFactory connectionFactory() {
    return ConnectionFactories.get(
            ConnectionFactoryOptions.builder()
                    .option(DRIVER, "postgresql")
                    .option(HOST, "localhost")
                    .option(PORT, 5432)
                    .option(USER, "admin")
                    .option(PASSWORD, "admin")
                    .option(DATABASE, "springdb")
                    .build());
   }
 }

On application start I'm getting:

Description:

Parameter 0 of constructor in com.springboot2.controller.ToDoController required a bean of type 'com.springboot2.repository.ToDoRepository' that could not be found.

Action:

Consider defining a bean of type 'com.springboot2.repository.ToDoRepository' in your configuration.

I tried to add @ComponentsScan, tried to move ToDoRepository to the root near Springboot2Application, I dont understand why Spring doesn't see repository interface

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>2.7.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springboot</groupId>
    <artifactId>springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot2</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>8</java.version>
        <spring-cloud.version>2021.0.3</spring-cloud.version>
<!--        <spring-shell.version>2.1.0</spring-shell.version>-->
    </properties>
    <dependencies>
        <!--        DB,ORM, and plugins-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-r2dbc</artifactId>
        </dependency>
        <dependency>
            <groupId>io.r2dbc</groupId>
            <artifactId>r2dbc-postgresql</artifactId>
            <version>0.8.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <!--        Reactive libs-->
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
Sam Fisher
  • 746
  • 2
  • 10
  • 27

1 Answers1

1

My guess the reason is that you have added r2dbc driver to your project, but haven't added spring-boot-starter-data-r2dbc

So, consider this dependency in your pom.xml file (this is the latest version at the time of writing this answer) :

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-r2dbc -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-r2dbc</artifactId>
    <version>3.0.2</version>
</dependency>

EDIT:

  1. Also you can try to use @EnableR2dbcRepositories and specify the package with your repository.

  2. One more possible way to solve this is to extend your repository from R2dbcRepository, instead of ReactiveCrudRepository This may help when you have multiple spring data reactive modules (r2dbc and something else) being used in the same project. Since ReactiveCrudRepository is a generic interface Spring does not know how to properly configure these beans.

kerbermeister
  • 2,985
  • 3
  • 11
  • 30
  • unfortunately this didnt solve the problem..I added pom code to question – Sam Fisher Feb 07 '23 at 08:06
  • Also mvn clean install didn't help? Maybe try to add annotation @EnableR2dbcRepositories, try to specify the package where your repository located – kerbermeister Feb 07 '23 at 08:18
  • updated r2dbc config with this annotation(updated code in question). maven clean install provided surefire report with error: Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.springboot2.repository.ToDoRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} – Sam Fisher Feb 07 '23 at 08:46
  • Also, I can see spring-boot-starter-web dependency along with webflux in your pom.xml. In this case should be regular mvc autoconfigured, and maybe this is the reason why spring is not aware of reactive repositories.. Maybe try to remove spring-boot-starter-web dependency. And also remove spring-boot-starter-data-rest – kerbermeister Feb 07 '23 at 08:48
  • And one more option: try to extend your repository from R2dbcRepository, instead of ReactiveCrudRepository – kerbermeister Feb 07 '23 at 09:01
  • removed indicated dependencies and used r2dbc repo. so finally it works. but as I see problem was in interface - Spring could not find ReactiveCrudRepo, but easily found R2DBCRepo. This is strange, because guides from google indecate ReactiveCrudRepo.. – Sam Fisher Feb 07 '23 at 09:26
  • right, the only reason I know is when you have multiple spring data reactive modules (r2dbc and something else) being used in the same project. Since ReactiveCrudRepository is a generic interface Spring does not know how to properly configure these beans. But I don't see any others reactive data modules in your project. – kerbermeister Feb 07 '23 at 09:33
  • Also, updated my answer with possible solutions – kerbermeister Feb 07 '23 at 09:38