Skip to content

Commit 54e99d6

Browse files
committed
Auto-configure ObservationRegistry on ScheduledTaskRegistrar
The TaskSchedulingAutoConfiguration.taskScheduler auto-configuration now no longer backs off on SchedulingConfigurer beans. Closes gh-36119
1 parent 90a38b6 commit 54e99d6

File tree

5 files changed

+130
-14
lines changed

5 files changed

+130
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.scheduling;
18+
19+
import io.micrometer.observation.ObservationRegistry;
20+
21+
import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration;
22+
import org.springframework.boot.autoconfigure.AutoConfiguration;
23+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
24+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
26+
import org.springframework.context.annotation.Bean;
27+
import org.springframework.scheduling.annotation.SchedulingConfigurer;
28+
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
29+
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
30+
31+
/**
32+
* {@link EnableAutoConfiguration Auto-configuration} to enable observability for
33+
* scheduled tasks.
34+
*
35+
* @author Moritz Halbritter
36+
* @since 3.2.0
37+
*/
38+
@AutoConfiguration(after = ObservationAutoConfiguration.class)
39+
@ConditionalOnBean(ObservationRegistry.class)
40+
@ConditionalOnClass(ThreadPoolTaskScheduler.class)
41+
public class ScheduledTasksObservabilityAutoConfiguration {
42+
43+
@Bean
44+
ObservabilitySchedulingConfigurer observabilitySchedulingConfigurer(ObservationRegistry observationRegistry) {
45+
return new ObservabilitySchedulingConfigurer(observationRegistry);
46+
}
47+
48+
static final class ObservabilitySchedulingConfigurer implements SchedulingConfigurer {
49+
50+
private final ObservationRegistry observationRegistry;
51+
52+
ObservabilitySchedulingConfigurer(ObservationRegistry observationRegistry) {
53+
this.observationRegistry = observationRegistry;
54+
}
55+
56+
@Override
57+
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
58+
taskRegistrar.setObservationRegistry(this.observationRegistry);
59+
}
60+
61+
}
62+
63+
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ org.springframework.boot.actuate.autoconfigure.r2dbc.ConnectionFactoryHealthCont
9393
org.springframework.boot.actuate.autoconfigure.data.redis.RedisHealthContributorAutoConfiguration
9494
org.springframework.boot.actuate.autoconfigure.data.redis.RedisReactiveHealthContributorAutoConfiguration
9595
org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksEndpointAutoConfiguration
96+
org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksObservabilityAutoConfiguration
9697
org.springframework.boot.actuate.autoconfigure.security.reactive.ReactiveManagementWebSecurityAutoConfiguration
9798
org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
9899
org.springframework.boot.actuate.autoconfigure.session.SessionsEndpointAutoConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.scheduling;
18+
19+
import java.util.List;
20+
21+
import io.micrometer.observation.ObservationRegistry;
22+
import org.junit.jupiter.api.Test;
23+
24+
import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration;
25+
import org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksObservabilityAutoConfiguration.ObservabilitySchedulingConfigurer;
26+
import org.springframework.boot.autoconfigure.AutoConfiguration;
27+
import org.springframework.boot.autoconfigure.AutoConfigurations;
28+
import org.springframework.boot.context.annotation.ImportCandidates;
29+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
30+
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
34+
/**
35+
* Tests for {@link ScheduledTasksObservabilityAutoConfiguration}.
36+
*
37+
* @author Moritz Halbritter
38+
*/
39+
class ScheduledTasksObservabilityAutoConfigurationTests {
40+
41+
private final ApplicationContextRunner runner = new ApplicationContextRunner().withConfiguration(AutoConfigurations
42+
.of(ObservationAutoConfiguration.class, ScheduledTasksObservabilityAutoConfiguration.class));
43+
44+
@Test
45+
void shouldProvideObservabilitySchedulingConfigurer() {
46+
this.runner.run((context) -> assertThat(context).hasSingleBean(ObservabilitySchedulingConfigurer.class));
47+
}
48+
49+
@Test
50+
void observabilitySchedulingConfigurerShouldConfigureObservationRegistry() {
51+
ObservationRegistry observationRegistry = ObservationRegistry.create();
52+
ObservabilitySchedulingConfigurer configurer = new ObservabilitySchedulingConfigurer(observationRegistry);
53+
ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar();
54+
configurer.configureTasks(registrar);
55+
assertThat(registrar.getObservationRegistry()).isEqualTo(observationRegistry);
56+
}
57+
58+
@Test
59+
void isRegisteredInAutoConfigurationsFile() {
60+
List<String> configurations = ImportCandidates.load(AutoConfiguration.class, null).getCandidates();
61+
assertThat(configurations).contains(ScheduledTasksObservabilityAutoConfiguration.class.getName());
62+
}
63+
64+
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2022 the original author or authors.
2+
* Copyright 2012-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -31,7 +31,6 @@
3131
import org.springframework.boot.task.TaskSchedulerCustomizer;
3232
import org.springframework.context.annotation.Bean;
3333
import org.springframework.scheduling.TaskScheduler;
34-
import org.springframework.scheduling.annotation.SchedulingConfigurer;
3534
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
3635
import org.springframework.scheduling.config.TaskManagementConfigUtils;
3736

@@ -48,7 +47,7 @@ public class TaskSchedulingAutoConfiguration {
4847

4948
@Bean
5049
@ConditionalOnBean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
51-
@ConditionalOnMissingBean({ SchedulingConfigurer.class, TaskScheduler.class, ScheduledExecutorService.class })
50+
@ConditionalOnMissingBean({ TaskScheduler.class, ScheduledExecutorService.class })
5251
public ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder builder) {
5352
return builder.build();
5453
}

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfigurationTests.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,6 @@ void enableSchedulingWithExistingScheduledExecutorServiceBacksOff() {
122122
});
123123
}
124124

125-
@Test
126-
void enableSchedulingWithConfigurerBacksOff() {
127-
this.contextRunner.withUserConfiguration(SchedulingConfiguration.class, SchedulingConfigurerConfiguration.class)
128-
.run((context) -> {
129-
assertThat(context).doesNotHaveBean(TaskScheduler.class);
130-
TestBean bean = context.getBean(TestBean.class);
131-
assertThat(bean.latch.await(30, TimeUnit.SECONDS)).isTrue();
132-
assertThat(bean.threadNames).containsExactly("test-1");
133-
});
134-
}
135-
136125
@Test
137126
void enableSchedulingWithLazyInitializationInvokeScheduledMethods() {
138127
List<String> threadNames = new ArrayList<>();

0 commit comments

Comments
 (0)