如果我在 LocalCosmosDBConfig.java 中取消注释 cosmosAsyncClient 方法,则会收到以下警告。如果我在同一文件中取消注释 cosmosConfig 方法,则会收到类似的警告。应用程序是使用java、akka框架和azure cosmos DB开发的。应用程序最终在警告后抛出以下错误,甚至无法启动。
CosmosDBConfig.java
@Slf4j
@Configuration
@ConditionalOnProperty("condition")
public abstract class CosmosDBConfig extends AbstractCosmosConfiguration {
protected final CosmosProperties cosmosProperties;
protected CosmosDBConfig(CosmosProperties cosmosProperties) {
this.cosmosProperties = cosmosProperties;
}
@Override
public CosmosConfig cosmosConfig() {
return CosmosConfig.builder()
.enableQueryMetrics(cosmosProperties.isQueryMetricsEnabled())
.responseDiagnosticsProcessor(
responseDiagnostics -> log.info("{} Response Diagnostics {}",
getClassName(), responseDiagnostics
))
.build();
}
protected CosmosClientBuilder cosmosClientBuilder() {
CosmosClientBuilder builder = createCosmosClientBuilder();
setCosmosCredentials(builder);
return builder;
}
@Override
public CosmosAsyncClient cosmosAsyncClient(CosmosClientBuilder cosmosClientBuilder) {
return CosmosFactory.createCosmosAsyncClient(cosmosClientBuilder);
}
protected void setCosmosCredentials(CosmosClientBuilder builder) {
if (StringUtils.hasText(getKey())) {
log.info("Connecting to Cosmos DB using Azure Key Credentials");
builder.credential(new AzureKeyCredential(getKey()));
} else {
log.info("Connecting to Cosmos DB using Azure Token Credentials");
builder.credential(new DefaultAzureCredentialBuilder().build());
}
}
protected String getClassName() {
return this.getClass().getSimpleName().replaceAll("\\$.*", "");
}
// Children classes will need to implement creation of cosmosClientBuilder with required properties needed for its unique connection
abstract CosmosClientBuilder createCosmosClientBuilder();
// Children classes will need to implement how to retrieve its unique connection's key
abstract String getKey();
}
LocalCosmosDBConfig.java
@Slf4j
@Configuration
@ConditionalOnProperty("condition")
@EnableReactiveCosmosRepositories(basePackages = "com.example.repository",
reactiveCosmosTemplateRef = "localDatabaseTemplate")
public class LocalCosmosDBConfig extends CosmosDBConfig {
private static final String LOCAL_COSMOS_CLIENT_BUILDER = "localCosmosClientBuilder";
private static final String LOCAL_COSMOS_ASYNC_CLIENT = "localCosmosAsyncClient";
private static final String LOCAL_COSMOS_CONFIG = "localCosmosConfig";
@Value("${azure.cosmos.regions}")
private List<String> regions;
@Value("${azure.cosmos.endpoint-discovery-enabled}")
private boolean endpointDiscoveryEnabled;
public LocalCosmosDBConfig(CosmosProperties cosmosProperties) {
super(cosmosProperties);
}
@Override
protected CosmosClientBuilder createCosmosClientBuilder() {
log.info("Building {} Cosmos DB Connection for: {}", getClassName(),
cosmosProperties.getLocalUri()
);
return new CosmosClientBuilder().endpoint(cosmosProperties.getLocalUri())
.gatewayMode(new GatewayConnectionConfig())
.preferredRegions(regions)
.endpointDiscoveryEnabled(endpointDiscoveryEnabled);
}
@Override
protected String getKey() {
return cosmosProperties.getLocalKey();
}
@Override
@Primary
@Bean(LOCAL_COSMOS_CLIENT_BUILDER)
public CosmosClientBuilder cosmosClientBuilder() {
return super.cosmosClientBuilder();
}
// @Override
// @Primary
// @Bean(LOCAL_COSMOS_ASYNC_CLIENT)
// public CosmosAsyncClient cosmosAsyncClient(
// @Qualifier(LOCAL_COSMOS_CLIENT_BUILDER) CosmosClientBuilder cosmosClientBuilder) {
// log.info("Building {} Cosmos Async Client for: {}", getClassName(), cosmosProperties.getLocalUri());
// return super.cosmosAsyncClient(cosmosClientBuilder);
// }
// @Override
// @Primary
// @Bean(LOCAL_COSMOS_CONFIG)
// public CosmosConfig cosmosConfig() {
// return super.cosmosConfig();
// }
@Bean
public ReactiveCosmosTemplate localDatabaseTemplate(
// @Qualifier(LOCAL_COSMOS_ASYNC_CLIENT) CosmosAsyncClient cosmosAsyncClient,
// @Qualifier(LOCAL_COSMOS_CONFIG) CosmosConfig cosmosConfig,
CosmosAsyncClient cosmosAsyncClient,
CosmosConfig cosmosConfig,
MappingCosmosConverter mappingCosmosConverter) {
return new ReactiveCosmosTemplate(cosmosAsyncClient, cosmosProperties.getLocalDatabase(), cosmosConfig,
mappingCosmosConverter
);
}
@Override
protected String getDatabaseName() {
return cosmosProperties.getLocalDatabase();
}
@Bean
public CosmosAsyncContainer buildCloudBufferAsyncContainer(
// @Qualifier(LOCAL_COSMOS_ASYNC_CLIENT) CosmosAsyncClient cosmosAsyncClient
CosmosAsyncClient cosmosAsyncClient
) {
CosmosAsyncDatabase database = cosmosAsyncClient.getDatabase(this.getDatabaseName());
return database.getContainer(VehicleCloudEventsContainerName);
}
}
[警告] - [org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext] - 上下文初始化期间遇到异常 - 取消刷新尝试:org.springframework.beans.factory.BeanCreationException:创建名称为“cosmosAsyncClient”的 bean 时出错在类路径资源 [com/example/dispatcher/configuration/LocalCosmosDBConfig.class] 中:在类 [com.example.dispatcher.configuration.LocalCosmosDBConfig] 上找不到匹配的工厂方法:工厂 bean 'localCosmosDBConfig';工厂方法“cosmosAsyncClient()”。检查具有指定名称的方法是否存在并且它是非静态的。
[错误] - [akka.actor.SupervisorStrategy] - 创建名为“defaultValidator”的 bean 时出错:当该工厂的单例处于销毁状态时,不允许创建单例 bean(不要在销毁方法实现中从 BeanFactory 请求 bean! ) akka.actor.ActorInitializationException:akka://dispatcher/user/outboundStreamActor-1:创建期间出现异常,根本原因消息:[创建名称为“defaultValidator”的 bean 时出错:该工厂的单例正在销毁时不允许创建单例 bean(不要在 destroy 方法实现中从 BeanFactory 请求 bean!)]
在我发布问题的当天修复了这个问题,但现在在 stackoverflow.com 上回答。不重写方法解决了问题。这是工作代码。
CosmosDBConfig.java
public abstract class CosmosDBConfig extends AbstractCosmosConfiguration {
protected static final String MAPPING_COSMOS_CONVERTER = "mappingCosmosConverter";
@Override
@Bean(MAPPING_COSMOS_CONVERTER)
public MappingCosmosConverter mappingCosmosConverter(CosmosMappingContext cosmosMappingContext) {
// object mapper
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
mapper.registerModule(JsonFormat.getCloudEventJacksonModule(true, false));
mapper.registerModule(new JavaTimeModule());
mapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false);
return new MappingCosmosConverter(cosmosMappingContext, mapper);
}
}
LocalCosmosDBConfig.java
@RequiredArgsConstructor
@Configuration
@Slf4j
@ConditionalOnProperty("dispatcher.inbound-vehicle.enabled")
@EnableReactiveCosmosRepositories(basePackages = "com.gm.ultifi.rs.dispatcher.repository.local", reactiveCosmosTemplateRef = "localDatabaseTemplate")
public class LocalCosmosDBConfig extends CosmosDBConfig {
private static final String LOCAL_COSMOS_CLIENT_BUILDER = "localCosmosClientBuilder";
private static final String LOCAL_COSMOS_ASYNC_CLIENT = "localCosmosAsyncClient";
private static final String LOCAL_COSMOS_CONFIG = "localCosmosConfig";
private final @Qualifier("defaultAzureCredential") TokenCredential defaultAzureCredential;
@Value("${cosmos.local.source.database.endpoint}")
private String uri;
@Value("${cosmos.local.source.database.name}")
private String dbName;
@Primary
@Bean(LOCAL_COSMOS_CLIENT_BUILDER)
public CosmosClientBuilder getCosmosClientBuilder() {
log.info("Building Cosmos DB Connection for: {}", uri);
var cosmosClientBuilder = new CosmosClientBuilder()
.endpoint(uri)
.gatewayMode(new GatewayConnectionConfig());
setAzureCredentials(cosmosClientBuilder);
return cosmosClientBuilder;
}
private void setAzureCredentials(CosmosClientBuilder cosmosClientBuilder) {
log.info("Connecting to Cosmos DB using Managed Identity Token Credentials");
cosmosClientBuilder.credential(defaultAzureCredential);
}
@Primary
@Bean(LOCAL_COSMOS_ASYNC_CLIENT)
public CosmosAsyncClient getCosmosAsyncClient(
@Qualifier(LOCAL_COSMOS_CLIENT_BUILDER) CosmosClientBuilder cosmosClientBuilder) {
log.info("Building {} Cosmos Async Client for: {}", "LocalCosmosDBConfig", uri);
return super.cosmosAsyncClient(cosmosClientBuilder);
}
@Primary
@Bean(LOCAL_COSMOS_CONFIG)
public CosmosConfig getCosmosConfig() {
return super.cosmosConfig();
}
@Bean
public ReactiveCosmosTemplate localDatabaseTemplate(
@Qualifier(LOCAL_COSMOS_ASYNC_CLIENT) CosmosAsyncClient cosmosAsyncClient,
@Qualifier(LOCAL_COSMOS_CONFIG) CosmosConfig cosmosConfig,
@Qualifier(MAPPING_COSMOS_CONVERTER) MappingCosmosConverter mappingCosmosConverter) {
return new ReactiveCosmosTemplate(cosmosAsyncClient, dbName, cosmosConfig,
mappingCosmosConverter
);
}
@Override
public String getDatabaseName() {
return dbName;
}
}
GlobalCosmosDBConfig.java
@RequiredArgsConstructor
@Configuration
@Slf4j
@ConditionalOnProperty("dispatcher.inbound-vehicle.enabled")
@EnableReactiveCosmosRepositories(basePackages = "com.gm.ultifi.rs.dispatcher.repository.global", reactiveCosmosTemplateRef = "globalDatabaseTemplate")
public class GlobalCosmosDBConfig extends CosmosDBConfig {
private static final String GLOBAL_COSMOS_CLIENT_BUILDER = "globalCosmosClientBuilder";
private static final String GLOBAL_COSMOS_ASYNC_CLIENT = "globalCosmosAsyncClient";
private static final String GLOBAL_COSMOS_CONFIG = "globalCosmosConfig";
private final @Qualifier("defaultAzureCredential") TokenCredential defaultAzureCredential;
@Value("${cosmos.global.source.database.endpoint}")
private String uri;
@Value("${cosmos.global.source.database.name}")
private String dbName;
@Value("${cosmos.pref-regions}")
private String regions;
@Bean(GLOBAL_COSMOS_CLIENT_BUILDER)
public CosmosClientBuilder getCosmosClientBuilder() {
log.info("Building Cosmos DB Connection for: {}", uri);
var cosmosClientBuilder = new CosmosClientBuilder()
.endpoint(uri)
.preferredRegions(Arrays.asList(regions.split(",")))
.endpointDiscoveryEnabled(true)
.gatewayMode(new GatewayConnectionConfig());
setAzureCredentials(cosmosClientBuilder);
return cosmosClientBuilder;
}
private void setAzureCredentials(CosmosClientBuilder cosmosClientBuilder) {
log.info("Connecting to Cosmos DB using Managed Identity Token Credentials");
cosmosClientBuilder.credential(defaultAzureCredential);
}
@Bean(GLOBAL_COSMOS_ASYNC_CLIENT)
public CosmosAsyncClient getCosmosAsyncClient(
@Qualifier(GLOBAL_COSMOS_CLIENT_BUILDER) CosmosClientBuilder cosmosClientBuilder) {
log.info("Building {} Cosmos Async Client for: {}", "GlobalCosmosDBConfig", uri);
return super.cosmosAsyncClient(cosmosClientBuilder);
}
@Bean(GLOBAL_COSMOS_CONFIG)
public CosmosConfig getCosmosConfig() {
return super.cosmosConfig();
}
@Bean
public ReactiveCosmosTemplate globalDatabaseTemplate(
@Qualifier(GLOBAL_COSMOS_ASYNC_CLIENT) CosmosAsyncClient cosmosAsyncClient,
@Qualifier(GLOBAL_COSMOS_CONFIG) CosmosConfig cosmosConfig,
@Qualifier(MAPPING_COSMOS_CONVERTER) MappingCosmosConverter mappingCosmosConverter) {
return new ReactiveCosmosTemplate(cosmosAsyncClient, dbName, cosmosConfig,
mappingCosmosConverter
);
}
@Override
public String getDatabaseName() {
return dbName;
}
@Bean
public CosmosAsyncContainer buildCloudBufferAsyncContainer(
@Qualifier(GLOBAL_COSMOS_ASYNC_CLIENT) CosmosAsyncClient cosmosAsyncClient) {
CosmosAsyncDatabase database = cosmosAsyncClient.getDatabase(getDatabaseName());
return database.getContainer(VehicleCloudEventsContainerName);
}
}