跳到主要内容

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的形式便不行