【问题标题】:UnsatisfiedDependencyException when creating MongoTemplate bean创建 MongoTemplate bean 时出现 UnsatisfiedDependencyException
【发布时间】:2020-07-14 10:52:55
【问题描述】:

在 Spring mongo 中使用 Mongobee 进行迁移

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

group = 'fete.bird'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '14'
compileJava {
    options.compilerArgs += ["--enable-preview"]
}
repositories {
    mavenCentral()
}
ext {
    set('springCloudVersion', "Hoxton.SR6")
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
    implementation 'org.springdoc:springdoc-openapi-ui:1.4.3'
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    implementation 'org.springframework.cloud:spring-cloud-starter-config'
    implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'

    compile 'com.github.mongobee:mongobee:0.13'
}
dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

test {
    useJUnitPlatform()
}

为 MongoTemplate 做构造函数依赖导致错误org.springframework.beans.factory.UnsatisfiedDependencyException:Error creating bean with name 'mongoTemplate'

这里是配置代码

@Configuration
public class ProductMigration {
    private final Environment environment;
    private MongoTemplate mongoTemplate;
    private static final Logger logger = LoggerFactory.getLogger(FeteBirdProductApplication.class);

    public ProductMigration(Environment environment, MongoTemplate mongoTemplate) {
        this.environment = environment;
        this.mongoTemplate = mongoTemplate;
    }

    @Bean
    public Mongobee mongobee(){
        logger.info("Starting product migration ...");
        String mongoUri = environment.getProperty("spring.data.mongodb.uri");
        boolean migrationsEnabled = Boolean.parseBoolean(environment.getProperty("app.db.migrations.enabled"));
        Mongobee runner = new Mongobee(mongoUri);
        runner.setEnabled(migrationsEnabled);
        runner.setChangeLogsScanPackage("fete.bird.fetebirdproduct.migration");
        runner.setChangelogCollectionName("migrations");
        runner.setLockCollectionName("migrations_lock");
        runner.setMongoTemplate(this.mongoTemplate);
        logger.info("Product migration completed...");
        return runner;
    }
}

这个问题是由MongoTemplate的构造函数依赖引起的,但不知道如何解决这个问题,

我尝试了@Autowired,但没有解决同样的问题。

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mongoTemplate' defined in class path resource [org/springframework/boot/autoconfigure/data/mongo/MongoDatabaseFactoryDependentConfiguration.class]: Unsatisfied dependency expressed through method 'mongoTemplate' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mongoDatabaseFactory' defined in class path resource [org/springframework/boot/autoconfigure/data/mongo/MongoDatabaseFactoryConfiguration.class]: Unsatisfied dependency expressed through method 'mongoDatabaseFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongo' defined in class path resource [org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.mongodb.client.MongoClient]: Factory method 'mongo' threw exception; nested exception is java.lang.NoSuchFieldError: UNSPECIFIED
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:797) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:538) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1304) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1224) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    ... 25 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mongoDatabaseFactory' defined in class path resource [org/springframework/boot/autoconfigure/data/mongo/MongoDatabaseFactoryConfiguration.class]: Unsatisfied dependency expressed through method 'mongoDatabaseFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongo' defined in class path resource [org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.mongodb.client.MongoClient]: Factory method 'mongo' threw exception; nested exception is java.lang.NoSuchFieldError: UNSPECIFIED
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:797) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:538) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1304) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1224) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:884) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    ... 38 common frames omitted

【问题讨论】:

  • 异常消息中的java.lang.NoSuchFieldError 表明您的某些依赖项的版本不兼容。我猜这是导致问题的 Mongo 的 Java 驱动程序的版本。你能分享你项目的完整build.gradle吗?
  • @AndyWilkinson 添加了 gradle 文件

标签: java spring spring-boot spring-mongo mongobee


【解决方案1】:

Spring Boot 2.3 中包含的 Spring Data MongoDB 版本使用的是 Mongo 的 Driver 版本 4,但 Mongobee 依赖于版本 3。这两个版本具有不同的 Maven 坐标(组 ID 和工件 ID),因此您最终会使用它们在类路径上。这会导致驱动程序版本 4 中的一些代码使用版本 3 中的代码和 NoSuchFieldError 结果。

您可以通过从 Mongobee 依赖项中排除 Mongo Driver 来避免此问题:

compile('com.github.mongobee:mongobee:0.13') {
    exclude group: 'org.mongodb'
}

【讨论】:

  • 通过排除 mongoDb 我得到了错误,因为 Mongobee runner = new Mongobee(mongoUri); ^ com.mongodb.MongoClient 的类文件未找到
  • 我需要添加 compile "org.mongodb:mongo-java-driver:3.12.6" 以使其工作。这是更好的方法吗??
  • 现在我遇到了一个新问题 尝试调用不存在的方法。尝试从以下位置进行:org.springframework.data.mongodb.core.MongoTemplate.lambda$insertDocumentList$16(MongoTemplate.java:1468) 以下方法不存在:'com.mongodb.client.result.InsertManyResult com .mongodb.client.MongoCollection.insertMany(java.util.List)'
  • 您不能将 mongo-java-driver:3.12.6 与 Spring Boot 2.3 一起使用。它需要 Mongo 驱动程序的第 4 版。如果 Mongobee 需要 3.x,那么您要么必须降级到 Spring Boot 2.2,要么停止使用 Mongobee。我会推荐后者,因为 Mongobee 似乎已被放弃。有一个more-active fork,但它还没有升级到Mongo驱动的第4版。
  • 谢谢安迪,这对我来说很有意义。非常感谢
【解决方案2】:

您遇到了Spring Data MongoDB 的较新版本所需的 MongoDB Java 驱动程序与 mongobee 使用的驱动程序之间的不兼容问题。 Spring Data MongoDB 需要版本 4 的 Mongo Java 库,而 mongobee 需要版本 3。这两个版本互不兼容,不能在一个应用程序中同时使用。

各种迹象表明,mongobee 已被其创建者抛弃,最后一次提交是在 2018 年 3 月,此后创建者没有对问题作出回应。因此,不要期望发布该库的更新版本以支持新版本的 Mongo Java 驱动程序。

由于这个项目的放弃,几个后继库是从 mongobee 分叉出来的。据我所知,Mongock 是唯一剩下的积极维护的后继库。它支持 Mongo Java 库的版本 3 和版本 4。

Mongock 是 Mongobee 的重大演变,具有 built-in support for migrating from mongobee。除了对 Mongo Java 驱动程序第 4 版的内置支持外,它还具有与 Spring 和 Spring Boot 的可选内置集成。

因此,如果您希望将最新版本的 Spring Data MongoDB 与 mongobee 兼容的迁移库一起使用,Mongock 将是最简单、最直接的方法。

dependencies {
    [...]

    compile 'com.github.cloudyrock.mongock:mongock-api:4.1.14'
}

【讨论】:

    【解决方案3】:

    您似乎没有为“MongoTemplate”创建 bean

    为它创建一个 bean 并使用它为 Mongobee 设置MongoTemplate。

    以下是这样做的示例

    @Bean
    public MongoClient mongo() {
        return new MongoClient("localhost");
    }
    
    @Bean
    public MongoTemplate mongoTemplate() throws Exception {
       return new MongoTemplate(mongo(), "test");
    }
    

    那就用这个

    @Bean
    public Mongobee mongobee(){
        logger.info("Starting product migration ...");
        String mongoUri = environment.getProperty("spring.data.mongodb.uri");
        boolean migrationsEnabled = Boolean.parseBoolean(environment.getProperty("app.db.migrations.enabled"));
        Mongobee runner = new Mongobee(mongoUri);
        runner.setEnabled(migrationsEnabled);
        runner.setChangeLogsScanPackage("fete.bird.fetebirdproduct.migration");
        runner.setChangelogCollectionName("migrations");
        runner.setLockCollectionName("migrations_lock");
        runner.setMongoTemplate(mongoTemplate());
        logger.info("Product migration completed...");
        return runner;
    }
    

    现在,您不必使用构造函数依赖项,以后可以在任何需要使用 MongoTemplate 的地方使用

     @Autowired  
     MongoTemplate mongoTemplate;
    

    希望这能解决你的问题!!

    【讨论】:

    • 添加在下面的答案中
    • 这实际上不起作用,因为问题是由于用于 mongobee 的 MongoDB Java 库版本与 Spring Data MongoDB 之间的不兼容。我已经写了一个解释,详细解释了这个问题。
    【解决方案4】:

    来了,

    @Bean
    public MongoClient mongo() {
        return new MongoClient("localhost");
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-07
      • 1970-01-01
      • 2020-11-16
      • 2015-06-19
      • 2019-06-15
      • 2021-11-18
      • 2022-01-04
      • 2017-05-21
      • 2021-06-20
      相关资源
      最近更新 更多