From 6f86e28b4856c50fd2ca7c1f75cd14829bc64d57 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 19 Jan 2023 15:13:22 +0100 Subject: [PATCH] GH-2612 Fix initialization ordering issue with actuator endpoints this also includes improvement where channels are now retrieved dynamically allowing new channels created during the runtime of the application to be visible as well Resolves #2612 --- .../ChannelsEndpointAutoConfiguration.java | 12 +++------ .../stream/endpoint/ChannelsEndpoint.java | 26 ++++++++++++------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/ChannelsEndpointAutoConfiguration.java b/core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/ChannelsEndpointAutoConfiguration.java index d5e9cc14a..88cde2152 100644 --- a/core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/ChannelsEndpointAutoConfiguration.java +++ b/core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/ChannelsEndpointAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2017 the original author or authors. + * Copyright 2015-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,16 +16,12 @@ package org.springframework.cloud.stream.config; -import java.util.List; - -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.cloud.stream.binding.Bindable; import org.springframework.cloud.stream.binding.BindingService; import org.springframework.cloud.stream.endpoint.ChannelsEndpoint; import org.springframework.context.annotation.Bean; @@ -34,6 +30,7 @@ import org.springframework.context.annotation.Bean; * @author Dave Syer * @author Marius Bogoevici * @author Ilayaperumal Gopinathan + * @author Oleg Zhurakousky */ @AutoConfiguration @ConditionalOnClass(name = "org.springframework.boot.actuate.endpoint.annotation.Endpoint") @@ -41,13 +38,10 @@ import org.springframework.context.annotation.Bean; @AutoConfigureAfter(EndpointAutoConfiguration.class) public class ChannelsEndpointAutoConfiguration { - @Autowired(required = false) - private List adapters; - @Bean @ConditionalOnAvailableEndpoint public ChannelsEndpoint channelsEndpoint(BindingServiceProperties properties) { - return new ChannelsEndpoint(this.adapters, properties); + return new ChannelsEndpoint(properties); } } diff --git a/core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/endpoint/ChannelsEndpoint.java b/core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/endpoint/ChannelsEndpoint.java index 9b360ba28..796580bee 100644 --- a/core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/endpoint/ChannelsEndpoint.java +++ b/core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/endpoint/ChannelsEndpoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2016 the original author or authors. + * Copyright 2015-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,8 @@ package org.springframework.cloud.stream.endpoint; +import java.util.Collection; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.JsonInclude; @@ -25,11 +25,14 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.BeansException; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.cloud.stream.binding.Bindable; import org.springframework.cloud.stream.config.BindingProperties; import org.springframework.cloud.stream.config.BindingServiceProperties; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; /** * An {@link Endpoint} that has the binding information on all the {@link Bindable} @@ -38,26 +41,31 @@ import org.springframework.cloud.stream.config.BindingServiceProperties; * @author Dave Syer * @author Ilayaperumal Gopinathan * @author Vinicius Carvalho + * @author Oleg Zhurakousky */ @Endpoint(id = "channels") -public class ChannelsEndpoint { +public class ChannelsEndpoint implements ApplicationContextAware { - private List adapters; + private ApplicationContext applicationContext; - private BindingServiceProperties properties; + private final BindingServiceProperties properties; - public ChannelsEndpoint(List adapters, - BindingServiceProperties properties) { - this.adapters = adapters; + public ChannelsEndpoint(BindingServiceProperties properties) { this.properties = properties; } + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + @ReadOperation public Map channels() { + Collection adapters = applicationContext.getBeansOfType(Bindable.class).values(); ChannelsMetaData map = new ChannelsMetaData(); Map inputs = map.getInputs(); Map outputs = map.getOutputs(); - for (Bindable factory : this.adapters) { + for (Bindable factory : adapters) { for (String name : factory.getInputs()) { inputs.put(name, this.properties.getBindingProperties(name)); }