From ec871d675200c4cbefd75fa66388458052cc2188 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Tue, 28 Apr 2020 21:01:14 +0200 Subject: [PATCH] Fix StatusAggregator static initialization Prior to this commit, there was a cycle between `StatusAggregator` and `SimpleStatusAggregator`, which caused a static initialization bug - depending on which class (the implementation or its interface) was loaded first. This commit turns the static field of the `StatusAggregator` interface into a static method to avoid this problem. Fixes gh-21211 --- .../AvailabilityProbesHealthEndpointGroup.java | 2 +- .../AvailabilityProbesHealthEndpointGroupTests.java | 2 +- .../boot/actuate/health/SimpleStatusAggregator.java | 6 +++++- .../boot/actuate/health/StatusAggregator.java | 7 +++++-- .../actuate/health/SimpleStatusAggregatorTests.java | 11 +++++++++-- 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesHealthEndpointGroup.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesHealthEndpointGroup.java index 470ba31ef17..c8a42ca3bbf 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesHealthEndpointGroup.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesHealthEndpointGroup.java @@ -56,7 +56,7 @@ class AvailabilityProbesHealthEndpointGroup implements HealthEndpointGroup { @Override public StatusAggregator getStatusAggregator() { - return StatusAggregator.DEFAULT; + return StatusAggregator.getDefault(); } @Override diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesHealthEndpointGroupTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesHealthEndpointGroupTests.java index 45f45f667b5..1a80c04dc12 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesHealthEndpointGroupTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesHealthEndpointGroupTests.java @@ -57,7 +57,7 @@ class AvailabilityProbesHealthEndpointGroupTests { @Test void getStatusAggregatorReturnsDefaultStatusAggregator() { - assertThat(this.group.getStatusAggregator()).isEqualTo(StatusAggregator.DEFAULT); + assertThat(this.group.getStatusAggregator()).isEqualTo(StatusAggregator.getDefault()); } @Test diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleStatusAggregator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleStatusAggregator.java index 748dac15503..42d200bcb3e 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleStatusAggregator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleStatusAggregator.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -37,6 +37,9 @@ import org.springframework.util.ObjectUtils; public class SimpleStatusAggregator implements StatusAggregator { private static final List DEFAULT_ORDER; + + static final StatusAggregator INSTANCE; + static { List defaultOrder = new ArrayList<>(); defaultOrder.add(Status.DOWN.getCode()); @@ -44,6 +47,7 @@ public class SimpleStatusAggregator implements StatusAggregator { defaultOrder.add(Status.UP.getCode()); defaultOrder.add(Status.UNKNOWN.getCode()); DEFAULT_ORDER = Collections.unmodifiableList(getUniformCodes(defaultOrder.stream())); + INSTANCE = new SimpleStatusAggregator(); } private final List order; diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/StatusAggregator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/StatusAggregator.java index 91a76b93a7d..82f4be77b6d 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/StatusAggregator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/StatusAggregator.java @@ -33,10 +33,13 @@ import java.util.Set; public interface StatusAggregator { /** - * A {@link StatusAggregator} instance using default ordering rules. + * Return {@link StatusAggregator} instance using default ordering rules. + * @return a {@code StatusAggregator} with default ordering rules. * @since 2.3.0 */ - StatusAggregator DEFAULT = new SimpleStatusAggregator(); + static StatusAggregator getDefault() { + return SimpleStatusAggregator.INSTANCE; + } /** * Return the aggregate status for the given set of statuses. diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SimpleStatusAggregatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SimpleStatusAggregatorTests.java index 2a9ccf4c068..1e0b9ab4412 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SimpleStatusAggregatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SimpleStatusAggregatorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -29,7 +29,14 @@ import static org.assertj.core.api.Assertions.assertThat; class SimpleStatusAggregatorTests { @Test - void getAggregateStatusWhenUsingDefaultOrder() { + void getAggregateStatusWhenUsingDefaultInstance() { + StatusAggregator aggregator = StatusAggregator.getDefault(); + Status status = aggregator.getAggregateStatus(Status.DOWN, Status.UP, Status.UNKNOWN, Status.OUT_OF_SERVICE); + assertThat(status).isEqualTo(Status.DOWN); + } + + @Test + void getAggregateStatusWhenUsingNewDefaultOrder() { SimpleStatusAggregator aggregator = new SimpleStatusAggregator(); Status status = aggregator.getAggregateStatus(Status.DOWN, Status.UP, Status.UNKNOWN, Status.OUT_OF_SERVICE); assertThat(status).isEqualTo(Status.DOWN);