You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot Data REST对接MongoDB遇Binary转UUID转换器缺失问题求助

问题背景

我有一个基于Spring Boot的标准微服务,采用Spring Data REST对接单个MongoDB固定大小集合(capped collection),文档包含UUID字段。本地构建运行正常,但生产环境Docker中启动时抛出如下错误:

{"timestamp":"2023-01-13T15:10:01.592Z","message":"Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.bson.types.Binary] to type [java.util.UUID]] with root cause", "component":"org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]","level":"ERROR","stack_trace":"org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.bson.types.Binary] to type [java.util.UUID]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:322)...
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.doConvert(MappingMongoConverter.java:1826)...
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.findAll(SimpleMongoRepository.java:444)

疑问

  1. 该如何处理此问题?能否通过Spring配置解决?
  2. 为何应用启动时会调用SimpleMongoRepository.findAll()?
  3. 我们有多个对接MongoDB的应用运行正常,为何Spring Data REST会出现此问题?
  4. 为何构建正常,但容器启动时失败?

相关代码与配置

仓库定义

@RepositoryRestResource( collectionResourceRel = 'events', path = 'events' )
interface EventRepository extends MongoRepository<EventMessage, String> { }

集合配置

class CustomApplicationRunner implements ApplicationRunner {

    @Autowired
    MongoTemplate mongoTemplate

    @Autowired
    ApplicationProperties configuration

    @Override
    void run(ApplicationArguments args) throws Exception {
        mongoTemplate.writeResultChecking = WriteResultChecking.EXCEPTION
        if ( !mongoTemplate.collectionExists( EventMessage ) ) {
            mongoTemplate.createCollection(EventMessage, new CollectionOptions(
                    configuration.mongoCollectionMaxSizeBytes,
                    configuration.mongoCollectionMaxDocuments,
                    configuration.mongoCappedCollection )
            )
        }
    }
}

开发环境MongoDB配置(application.yml)

mongodb:
      uri: mongodb://mongodb:27017/development
      auto-index-creation: true
      uuid-representation: STANDARD
      authentication-database: admin

Spring Boot依赖

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'org.springframework.boot:spring-boot-starter-amqp'
    implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
    implementation 'org.springframework.boot:spring-boot-starter-integration'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-rest'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

版本信息

  • SpringBoot 2.7.7
  • Groovy 4.0.6

已做调研

  • MongoDB驱动曾有关于Binary与UUID互转的问题,但仅更新了BsonBinary的转换支持,未覆盖org.bson.types.Binary场景。
  • Spring Data MongoDB的相关问题中有人提供了自定义转换器的解决方案,但不确定是否为唯一方案。

解答

1. 问题处理方案(含配置方式)

优先检查配置一致性

首先确认生产环境的uuid-representation配置是否为STANDARD。如果生产环境该配置缺失或值不正确,MongoDB驱动会用旧的UUID存储格式(将UUID转为Binary类型),而Spring Data无法自动转换这种格式到UUID。另外注意Spring Boot 2.x中该配置的正确前缀是spring.data.mongodb,补充生产环境的application.yml配置:

spring:
  data:
    mongodb:
      uuid-representation: STANDARD

自定义转换器(配置无法解决时)

如果配置正确但问题依旧,需要手动添加Binary到UUID的转换器:

import org.bson.types.Binary
import org.springframework.core.convert.converter.Converter
import org.springframework.data.convert.ReadingConverter
import java.util.UUID

@ReadingConverter
class BinaryToUuidConverter implements Converter<Binary, UUID> {
    @Override
    UUID convert(Binary source) {
        if (source == null) {
            return null
        }
        // 根据实际存储格式调整:如果是UUID直接转的字节,可改用new UUID(bytes[0..7], bytes[8..15])
        return UUID.nameUUIDFromBytes(source.getData())
    }
}

然后注册转换器到Mongo配置:

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.mongodb.core.convert.MongoCustomConversions

@Configuration
class MongoConfig {
    @Bean
    MongoCustomConversions mongoCustomConversions() {
        return new MongoCustomConversions([new BinaryToUuidConverter()])
    }
}

2. 启动时调用findAll()的原因

Spring Data REST在启动时会为暴露的Repository生成HAL元数据,其中会尝试获取集合的样本数据来生成响应的Schema(比如/events接口的OPTIONS请求元数据)。如果你的固定大小集合已有数据,启动时Spring Data REST会触发findAll()来获取样本,进而触发类型转换。

3. Spring Data REST单独出问题的原因

其他对接MongoDB的应用可能没有使用Spring Data REST的自动元数据生成逻辑,不会在启动时主动查询集合数据;或者它们的UUID字段是用STANDARD格式存储为BsonBinary,而非旧的Binary类型。而Spring Data REST的启动元数据生成会主动触发数据查询,暴露了转换问题。

4. 构建正常但容器启动失败的原因

构建阶段仅做编译和依赖检查,不会实际连接MongoDB并执行数据查询。容器启动时,应用会初始化Spring上下文、连接MongoDB,同时Spring Data REST触发元数据生成查询,此时才会读取集合中的数据,触发类型转换错误。而本地环境可能集合中没有数据(或数据是用STANDARD格式存储的),所以启动时不会触发转换问题。


内容的提问来源于stack exchange,提问作者Serhii Mormul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 09:06:39