【已解决】GraalVM mongodb-reactive SpringNative,Java能正常运行,但是编译出的可执行文件无法连接到mongo

问题复现

依赖中选用的是:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>

增加了MongoConfig

import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.gridfs.ReactiveGridFsTemplate;
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;

@Configuration
@EnableReactiveMongoRepositories("run.runnable.xxx.repository")
public class MongoConfig extends AbstractReactiveMongoConfiguration {

    @Value("${spring.data.mongodb.host}")
    String host;

    @Value("${spring.data.mongodb.port}")
    String port;

    @Value("${spring.data.mongodb.username}")
    String username;

    @Value("${spring.data.mongodb.password}")
    String password;

    @Value("${spring.data.mongodb.database}")
    String database;

    @Override
    protected String getDatabaseName() {
        return database;
    }

    @Override
    public MongoClient reactiveMongoClient() {
        String uri = 
        return MongoClients.create(uri);
    }

    @Bean
    public ReactiveGridFsTemplate reactiveGridFsTemplate(MappingMongoConverter mappingMongoConverter) {
        return new ReactiveGridFsTemplate(reactiveMongoDbFactory(), mappingMongoConverter, "attachments");
    }

    private MongoClient mongoClient;
    @Autowired
    public void setMongoClient(MongoClient mongoClient) {
        this.mongoClient = mongoClient;
    }

    @Bean
    public ReactiveMongoTemplate reactiveMongoTemplate() {
        return new ReactiveMongoTemplate(mongoClient, getDatabaseName());
    }
}

yaml配置大概如下

spring:
  data:
    mongodb:
      host: host
      username: username
      password: password
      database: database
      port: 27017

使用Java版进行启动和连接操作数据库都没问题,但是编译成可执行文件后启动便会抛错,错误信息如下:

Caused by: com.mongodb.MongoCommandException: Command failed with error 18 (AuthenticationFailed): 'Authentication failed.' on server host. The full response is {"ok": 0.0, "errmsg": "Authentication failed.", "code": 18, "codeName": "AuthenticationFailed"}
        at com.mongodb.internal.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:205) ~[na:na]
        at com.mongodb.internal.connection.InternalStreamConnection.lambda$sendCommandMessageAsync$0(InternalStreamConnection.java:539) ~[na:na]
        ... 36 common frames omitted

解决办法

在我网上搜了一圈但是都没有找到解决办法,我猜测肯定以前是有人这样已经缝合玩过了,我便去github上搜,还真让我找到一个,把他的代码拉下来,更新一下最新版本的SpringBoot,切换一下SpringBoot连接,什么!他的竟然是可以的,我检查了一下他的配置和我的配置区别,才发现人家根本没增加什么MongoConfig,直接在application.properties中写了连接的url

这里我对他的代码做了一下更改,然后重新推到了github,地址:https://github.com/MingGH/spring-native-demo
你可以直接拉下来尝试配置启动

spring.data.mongodb.uri=mongodb://localhost:27017/blog
logging.level.root=INFO
logging.level.org.springframework.aot=TRACE

于是我便删除了我的MongoConfig, 在application.yaml中配置

spring:
  data:
    mongodb:
      uri: mongodb://localhost:27017/blog

再进行编译,没想到还真的可以了。。。猜测是SpringNative对自动装配做了兼容,能把参数正确注入,但是使用MongoConfig的形式便不行

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×