Skip to content

Commit

Permalink
Avoid actuator beans being ineligible for post-processing
Browse files Browse the repository at this point in the history
Closes gh-33110
  • Loading branch information
wilkinsona committed Nov 11, 2022
1 parent b5e502d commit fe72f30
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 44 deletions.
Expand Up @@ -21,10 +21,12 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;

import com.fasterxml.jackson.databind.ObjectMapper;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
Expand Down Expand Up @@ -67,6 +69,7 @@
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.util.StringUtils;
import org.springframework.util.function.SingletonSupplier;
import org.springframework.web.reactive.DispatcherHandler;

/**
Expand Down Expand Up @@ -134,8 +137,9 @@ public ControllerEndpointHandlerMapping controllerEndpointHandlerMapping(
@ConditionalOnBean(EndpointObjectMapper.class)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static ServerCodecConfigurerEndpointObjectMapperBeanPostProcessor serverCodecConfigurerEndpointObjectMapperBeanPostProcessor(
EndpointObjectMapper endpointObjectMapper) {
return new ServerCodecConfigurerEndpointObjectMapperBeanPostProcessor(endpointObjectMapper);
ObjectProvider<EndpointObjectMapper> endpointObjectMapper) {
return new ServerCodecConfigurerEndpointObjectMapperBeanPostProcessor(
SingletonSupplier.of(endpointObjectMapper::getObject));
}

/**
Expand All @@ -147,9 +151,10 @@ static class ServerCodecConfigurerEndpointObjectMapperBeanPostProcessor implemen
private static final List<MediaType> MEDIA_TYPES = Collections
.unmodifiableList(Arrays.asList(MediaType.APPLICATION_JSON, new MediaType("application", "*+json")));

private final EndpointObjectMapper endpointObjectMapper;
private final Supplier<EndpointObjectMapper> endpointObjectMapper;

ServerCodecConfigurerEndpointObjectMapperBeanPostProcessor(EndpointObjectMapper endpointObjectMapper) {
ServerCodecConfigurerEndpointObjectMapperBeanPostProcessor(
Supplier<EndpointObjectMapper> endpointObjectMapper) {
this.endpointObjectMapper = endpointObjectMapper;
}

Expand All @@ -173,7 +178,7 @@ private void process(Encoder<?> encoder) {
if (encoder instanceof Jackson2JsonEncoder) {
Jackson2JsonEncoder jackson2JsonEncoder = (Jackson2JsonEncoder) encoder;
jackson2JsonEncoder.registerObjectMappersForType(OperationResponseBody.class, (associations) -> {
ObjectMapper objectMapper = this.endpointObjectMapper.get();
ObjectMapper objectMapper = this.endpointObjectMapper.get().get();
MEDIA_TYPES.forEach((mimeType) -> associations.put(mimeType, objectMapper));
});
}
Expand Down
Expand Up @@ -44,7 +44,7 @@ class MeterRegistryPostProcessor implements BeanPostProcessor, SmartInitializing

private final boolean hasNoCompositeMeterRegistryBeans;

private final boolean useGlobalRegistry;
private final ObjectProvider<MetricsProperties> properties;

private final ObjectProvider<MeterRegistryCustomizer<?>> customizers;

Expand All @@ -56,22 +56,21 @@ class MeterRegistryPostProcessor implements BeanPostProcessor, SmartInitializing

private final Set<MeterRegistry> deferredBindings = new LinkedHashSet<>();

MeterRegistryPostProcessor(ApplicationContext applicationContext, MetricsProperties metricsProperties,
ObjectProvider<MeterRegistryCustomizer<?>> customizers, ObjectProvider<MeterFilter> filters,
ObjectProvider<MeterBinder> binders) {
this(hasNoCompositeMeterRegistryBeans(applicationContext), metricsProperties.isUseGlobalRegistry(), customizers,
filters, binders);
MeterRegistryPostProcessor(ApplicationContext applicationContext,
ObjectProvider<MetricsProperties> metricsProperties, ObjectProvider<MeterRegistryCustomizer<?>> customizers,
ObjectProvider<MeterFilter> filters, ObjectProvider<MeterBinder> binders) {
this(hasNoCompositeMeterRegistryBeans(applicationContext), metricsProperties, customizers, filters, binders);
}

private static boolean hasNoCompositeMeterRegistryBeans(ApplicationContext applicationContext) {
return applicationContext.getBeanNamesForType(CompositeMeterRegistry.class, false, false).length == 0;
}

MeterRegistryPostProcessor(boolean hasNoCompositeMeterRegistryBeans, boolean useGlobalRegistry,
MeterRegistryPostProcessor(boolean hasNoCompositeMeterRegistryBeans, ObjectProvider<MetricsProperties> properties,
ObjectProvider<MeterRegistryCustomizer<?>> customizers, ObjectProvider<MeterFilter> filters,
ObjectProvider<MeterBinder> binders) {
this.hasNoCompositeMeterRegistryBeans = hasNoCompositeMeterRegistryBeans;
this.useGlobalRegistry = useGlobalRegistry;
this.properties = properties;
this.customizers = customizers;
this.filters = filters;
this.binders = binders;
Expand Down Expand Up @@ -121,7 +120,7 @@ private void applyFilters(MeterRegistry meterRegistry) {
}

private void addToGlobalRegistryIfNecessary(MeterRegistry meterRegistry) {
if (this.useGlobalRegistry && !isGlobalRegistry(meterRegistry)) {
if (this.properties.getObject().isUseGlobalRegistry() && !isGlobalRegistry(meterRegistry)) {
Metrics.addRegistry(meterRegistry);
}
}
Expand Down
Expand Up @@ -51,7 +51,8 @@ public Clock micrometerClock() {

@Bean
public static MeterRegistryPostProcessor meterRegistryPostProcessor(ApplicationContext applicationContext,
MetricsProperties metricsProperties, ObjectProvider<MeterRegistryCustomizer<?>> meterRegistryCustomizers,
ObjectProvider<MetricsProperties> metricsProperties,
ObjectProvider<MeterRegistryCustomizer<?>> meterRegistryCustomizers,
ObjectProvider<MeterFilter> meterFilters, ObjectProvider<MeterBinder> meterBinders) {
return new MeterRegistryPostProcessor(applicationContext, metricsProperties, meterRegistryCustomizers,
meterFilters, meterBinders);
Expand Down
Expand Up @@ -48,6 +48,8 @@
@ExtendWith(MockitoExtension.class)
class MeterRegistryPostProcessorTests {

private final MetricsProperties properties = new MetricsProperties();

private List<MeterRegistryCustomizer<?>> customizers = new ArrayList<>();

private List<MeterFilter> filters = new ArrayList<>();
Expand All @@ -69,12 +71,16 @@ class MeterRegistryPostProcessorTests {
@Mock
private Config mockConfig;

MeterRegistryPostProcessorTests() {
this.properties.setUseGlobalRegistry(false);
}

@Test
void postProcessAndInitializeWhenCompositeAppliesCustomizer() {
this.customizers.add(this.mockCustomizer);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(false, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(false,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
CompositeMeterRegistry composite = new CompositeMeterRegistry();
postProcessAndInitialize(processor, composite);
then(this.mockCustomizer).should().customize(composite);
Expand All @@ -84,9 +90,9 @@ void postProcessAndInitializeWhenCompositeAppliesCustomizer() {
void postProcessAndInitializeAppliesCustomizer() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
this.customizers.add(this.mockCustomizer);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
postProcessAndInitialize(processor, this.mockRegistry);
then(this.mockCustomizer).should().customize(this.mockRegistry);
}
Expand All @@ -95,9 +101,9 @@ void postProcessAndInitializeAppliesCustomizer() {
void postProcessAndInitializeAppliesFilter() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
this.filters.add(this.mockFilter);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
postProcessAndInitialize(processor, this.mockRegistry);
then(this.mockConfig).should().meterFilter(this.mockFilter);
}
Expand All @@ -106,19 +112,19 @@ void postProcessAndInitializeAppliesFilter() {
void postProcessAndInitializeBindsTo() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
this.binders.add(this.mockBinder);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
postProcessAndInitialize(processor, this.mockRegistry);
then(this.mockBinder).should().bindTo(this.mockRegistry);
}

@Test
void postProcessAndInitializeWhenCompositeBindsTo() {
this.binders.add(this.mockBinder);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(false, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(false,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
CompositeMeterRegistry composite = new CompositeMeterRegistry();
postProcessAndInitialize(processor, composite);
then(this.mockBinder).should().bindTo(composite);
Expand All @@ -127,8 +133,9 @@ void postProcessAndInitializeWhenCompositeBindsTo() {
@Test
void postProcessAndInitializeWhenCompositeExistsDoesNotBindTo() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(false, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters), null);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(false,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), null);
postProcessAndInitialize(processor, this.mockRegistry);
then(this.mockBinder).shouldHaveNoInteractions();
}
Expand All @@ -139,9 +146,9 @@ void postProcessAndInitializeBeOrderedCustomizerThenFilterThenBindTo() {
this.customizers.add(this.mockCustomizer);
this.filters.add(this.mockFilter);
this.binders.add(this.mockBinder);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
postProcessAndInitialize(processor, this.mockRegistry);
InOrder ordered = inOrder(this.mockBinder, this.mockConfig, this.mockCustomizer);
then(this.mockCustomizer).should(ordered).customize(this.mockRegistry);
Expand All @@ -152,9 +159,10 @@ void postProcessAndInitializeBeOrderedCustomizerThenFilterThenBindTo() {
@Test
void postProcessAndInitializeWhenUseGlobalRegistryTrueAddsToGlobalRegistry() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, true,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
this.properties.setUseGlobalRegistry(true);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
try {
postProcessAndInitialize(processor, this.mockRegistry);
assertThat(Metrics.globalRegistry.getRegistries()).contains(this.mockRegistry);
Expand All @@ -167,9 +175,9 @@ void postProcessAndInitializeWhenUseGlobalRegistryTrueAddsToGlobalRegistry() {
@Test
void postProcessAndInitializeWhenUseGlobalRegistryFalseDoesNotAddToGlobalRegistry() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
postProcessAndInitialize(processor, this.mockRegistry);
assertThat(Metrics.globalRegistry.getRegistries()).doesNotContain(this.mockRegistry);
}
Expand All @@ -178,9 +186,9 @@ void postProcessAndInitializeWhenUseGlobalRegistryFalseDoesNotAddToGlobalRegistr
void postProcessDoesNotBindToUntilSingletonsInitialized() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
this.binders.add(this.mockBinder);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
processor.postProcessAfterInitialization(this.mockRegistry, "meterRegistry");
then(this.mockBinder).shouldHaveNoInteractions();
processor.afterSingletonsInstantiated();
Expand All @@ -199,4 +207,11 @@ private <T> ObjectProvider<T> createObjectProvider(List<T> objects) {
return objectProvider;
}

@SuppressWarnings("unchecked")
private <T> ObjectProvider<T> createObjectProvider(T object) {
ObjectProvider<T> objectProvider = mock(ObjectProvider.class);
given(objectProvider.getObject()).willReturn(object);
return objectProvider;
}

}

0 comments on commit fe72f30

Please sign in to comment.