简体   繁体   中英

Application won't start as MongoOperations bean is not defined

I'm working through the book Learning Spring Boot 2.0, Second Edition but using Spring Boot 2.5.6 so I suspect my issue might be related to me having to do things slightly with the different version.

I have this class:

@Component
public class InitDatabase {

    @Bean
    CommandLineRunner init(MongoOperations operations) {
        return args -> {
            operations.dropCollection(Image.class);

            operations.insert(new Image("1", "learning-spring-boot-cover.jpg"));
            operations.insert(new Image("2", "learning-spring-boot-2nd-edition-cover.jpg"));
            operations.insert(new Image("3", "bazinga.png"));

            operations.findAll(Image.class).forEach(image -> System.out.println(image.toString()));
        };
    }

}

When I run my application I get this error:

2021-11-25 12:26:42.870 DEBUG 71010 --- [ main] osbdLoggingFailureAnalysisReporter: Application failed to start due to an exception

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.mongodb.core.MongoOperations' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1790) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1346) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentA rray(ConstructorResolver.java:791) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:541) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Z93F725A07423FE1C889F448B33D21F 46Z:582) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.AbstractBeanFactory. getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.12.jar:5.3.12] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.12.jar:5.3.12] at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:64) ~[spring-boot-2.5.6.jar:2.5.6] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-2.5.6.jar:2.5.6] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[spring-boot-2.5.6.jar:2.5.6] at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) ~[spring-boot-2.5.6.jar:2.5.6] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-2.5.6.jar:2.5.6] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332) ~[spring-boot-2.5.6.jar:2.5.6] at com.paulcarron.learningspringboot.le arningspringboot.LearningSpringBootApplication.main(LearningSpringBootApplication.java:12) ~[classes/:na]

2021-11-25 12:26:42.870 ERROR 71010 --- [ main] osbdLoggingFailureAnalysisReporter:


APPLICATION FAILED TO START


Description:

Parameter 0 of method init in com.paulcarron.learningspringboot.learningspringboot.InitDatabase required a bean of type 'org.springframework.data.mongodb.core.MongoOperations' that could not be found.

Action:

Consider defining a bean of type 'org.springframework.data.mongodb.core.MongoOperations' in your configuration.

This is my build.gradle :

plugins {
    id 'org.springframework.boot' version '2.5.6'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group = 'com.paulcarron.learningspringboot'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    implementation 'org.synchronoss.cloud:nio-multipart-parser:1.1.0'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'de.flapdoodle.embed:de.flapdoodle.embed.mongo'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'io.projectreactor:reactor-test'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'javax.persistence:javax.persistence-api:2.2'
}

test {
    useJUnitPlatform()
}

My understanding is that I don't need to activate the with @EnableReactiveMongoRepositories as this is done automatically if Reactive MongoDB or Spring DataMongoDB 2.0+ are on the classpath.

Is there any obvious reason why this is not working?

I guess you're trying to init your database on the startup.

You can leverage the spring internal event mechanism. When your application is ready, spring triggers the event ApplicationReadyEvent

You can listen to this event and init your collection:

@Component
public class DataInit implements ApplicationListener<ApplicationReadyEvent> {

    private final MongoOperations operations;

    public DataInit(MongoOperations operations) {
        this.operations = operations;
    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // init data
    }
}

If you want to know more about spring events --> https://www.baeldung.com/spring-events

MongoOperations is the interface for interacting with Mongo in a blocking manner. ReactiveMongoOperations is the interface for interacting with Mongo in a reactive manner.

As you're using WebFlux ( spring-boot-starter-webflux ), it would appear that you want to build a reactive application. If so, you should replace your use of MongoOperations with ReactiveMongoOperations . The, if you want to build a blocking, Servlet-based web application would be to switch to spring-boot-starter-data-mongodb and spring-boot-starter-web .

I want to preload data and read that it was best to do this using a blocking API because when launching an application there is a risk of a thread lock issue when both the web container and my loader are starting up. The book I'm using is for an older veriosn of both Spring Boot and MongoDB.

It seems that the version of spring-boot-starter-data-mongodb-reactive that the book used contained MongoOperations but this was then split out. See this .

To use this I added implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' to my class path.

If there wasn't the issue of thread lock I could have used ReactiveMongoOperations instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM