Skip to content

Commit f1c1a4f

Browse files
committed
Merge pull request #28136 from jonatan-ivanov
* pr/28136: Polish "Add Java InfoContributor" Add Java InfoContributor Closes gh-28136
2 parents 0b58d48 + 5d17257 commit f1c1a4f

File tree

7 files changed

+341
-70
lines changed

7 files changed

+341
-70
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/info/InfoContributorAutoConfiguration.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2021 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.
@@ -20,6 +20,7 @@
2020
import org.springframework.boot.actuate.info.EnvironmentInfoContributor;
2121
import org.springframework.boot.actuate.info.GitInfoContributor;
2222
import org.springframework.boot.actuate.info.InfoContributor;
23+
import org.springframework.boot.actuate.info.JavaInfoContributor;
2324
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
2425
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
2526
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -40,6 +41,7 @@
4041
*
4142
* @author Meang Akira Tanaka
4243
* @author Stephane Nicoll
44+
* @author Jonatan Ivanov
4345
* @since 2.0.0
4446
*/
4547
@Configuration(proxyBeanMethods = false)
@@ -77,4 +79,11 @@ public InfoContributor buildInfoContributor(BuildProperties buildProperties) {
7779
return new BuildInfoContributor(buildProperties);
7880
}
7981

82+
@Bean
83+
@ConditionalOnEnabledInfoContributor("java")
84+
@Order(DEFAULT_ORDER)
85+
public JavaInfoContributor javaInfoContributor() {
86+
return new JavaInfoContributor();
87+
}
88+
8089
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/info/InfoContributorAutoConfigurationTests.java

Lines changed: 79 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2021 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.
@@ -19,17 +19,19 @@
1919
import java.util.Map;
2020
import java.util.Properties;
2121

22-
import org.junit.jupiter.api.AfterEach;
2322
import org.junit.jupiter.api.Test;
2423

2524
import org.springframework.boot.actuate.info.BuildInfoContributor;
25+
import org.springframework.boot.actuate.info.EnvironmentInfoContributor;
2626
import org.springframework.boot.actuate.info.GitInfoContributor;
2727
import org.springframework.boot.actuate.info.Info;
2828
import org.springframework.boot.actuate.info.InfoContributor;
29+
import org.springframework.boot.actuate.info.JavaInfoContributor;
30+
import org.springframework.boot.autoconfigure.AutoConfigurations;
2931
import org.springframework.boot.info.BuildProperties;
3032
import org.springframework.boot.info.GitProperties;
31-
import org.springframework.boot.test.util.TestPropertyValues;
32-
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
33+
import org.springframework.boot.info.JavaInfo;
34+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
3335
import org.springframework.context.annotation.Bean;
3436
import org.springframework.context.annotation.Configuration;
3537

@@ -39,94 +41,117 @@
3941
* Tests for {@link InfoContributorAutoConfiguration}.
4042
*
4143
* @author Stephane Nicoll
44+
* @author Jonatan Ivanov
4245
*/
4346
class InfoContributorAutoConfigurationTests {
4447

45-
private AnnotationConfigApplicationContext context;
48+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
49+
.withConfiguration(AutoConfigurations.of(InfoContributorAutoConfiguration.class));
4650

47-
@AfterEach
48-
void close() {
49-
if (this.context != null) {
50-
this.context.close();
51-
}
51+
@Test
52+
void disableEnvContributor() {
53+
this.contextRunner.withPropertyValues("management.info.env.enabled=false")
54+
.run((context) -> assertThat(context).doesNotHaveBean(EnvironmentInfoContributor.class));
5255
}
5356

5457
@Test
55-
void disableEnvContributor() {
56-
load("management.info.env.enabled:false");
57-
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
58-
assertThat(beans).hasSize(0);
58+
void disableJavaContributor() {
59+
this.contextRunner.withPropertyValues("management.info.java.enabled=false")
60+
.run((context) -> assertThat(context).doesNotHaveBean(JavaInfoContributor.class));
61+
}
62+
63+
@Test
64+
void defaultInfoContributorsEnabled() {
65+
this.contextRunner.run((context) -> {
66+
assertThat(context).hasSingleBean(EnvironmentInfoContributor.class)
67+
.hasSingleBean(JavaInfoContributor.class);
68+
assertThat(context.getBeansOfType(InfoContributor.class)).hasSize(2);
69+
});
5970
}
6071

6172
@Test
6273
void defaultInfoContributorsDisabled() {
63-
load("management.info.defaults.enabled:false");
64-
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
65-
assertThat(beans).hasSize(0);
74+
this.contextRunner.withPropertyValues("management.info.defaults.enabled=false")
75+
.run((context) -> assertThat(context).doesNotHaveBean(InfoContributor.class));
6676
}
6777

6878
@Test
6979
void defaultInfoContributorsDisabledWithCustomOne() {
70-
load(CustomInfoContributorConfiguration.class, "management.info.defaults.enabled:false");
71-
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
72-
assertThat(beans).hasSize(1);
73-
assertThat(this.context.getBean("customInfoContributor")).isSameAs(beans.values().iterator().next());
80+
this.contextRunner.withPropertyValues("management.info.defaults.enabled=false")
81+
.withUserConfiguration(CustomInfoContributorConfiguration.class).run((context) -> {
82+
assertThat(context).hasSingleBean(InfoContributor.class);
83+
assertThat(context.getBean(InfoContributor.class))
84+
.isSameAs(context.getBean("customInfoContributor"));
85+
});
7486
}
7587

7688
@SuppressWarnings("unchecked")
7789
@Test
7890
void gitPropertiesDefaultMode() {
79-
load(GitPropertiesConfiguration.class);
80-
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
81-
assertThat(beans).containsKeys("gitInfoContributor");
82-
Map<String, Object> content = invokeContributor(
83-
this.context.getBean("gitInfoContributor", InfoContributor.class));
84-
Object git = content.get("git");
85-
assertThat(git).isInstanceOf(Map.class);
86-
Map<String, Object> gitInfo = (Map<String, Object>) git;
87-
assertThat(gitInfo).containsOnlyKeys("branch", "commit");
91+
this.contextRunner.withUserConfiguration(GitPropertiesConfiguration.class).run((context) -> {
92+
assertThat(context).hasSingleBean(GitInfoContributor.class);
93+
Map<String, Object> content = invokeContributor(context.getBean(GitInfoContributor.class));
94+
Object git = content.get("git");
95+
assertThat(git).isInstanceOf(Map.class);
96+
Map<String, Object> gitInfo = (Map<String, Object>) git;
97+
assertThat(gitInfo).containsOnlyKeys("branch", "commit");
98+
});
8899
}
89100

90101
@SuppressWarnings("unchecked")
91102
@Test
92103
void gitPropertiesFullMode() {
93-
load(GitPropertiesConfiguration.class, "management.info.git.mode=full");
94-
Map<String, Object> content = invokeContributor(
95-
this.context.getBean("gitInfoContributor", InfoContributor.class));
96-
Object git = content.get("git");
97-
assertThat(git).isInstanceOf(Map.class);
98-
Map<String, Object> gitInfo = (Map<String, Object>) git;
99-
assertThat(gitInfo).containsOnlyKeys("branch", "commit", "foo");
100-
assertThat(gitInfo.get("foo")).isEqualTo("bar");
104+
this.contextRunner.withPropertyValues("management.info.git.mode=full")
105+
.withUserConfiguration(GitPropertiesConfiguration.class).run((context) -> {
106+
assertThat(context).hasSingleBean(GitInfoContributor.class);
107+
Map<String, Object> content = invokeContributor(context.getBean(GitInfoContributor.class));
108+
Object git = content.get("git");
109+
assertThat(git).isInstanceOf(Map.class);
110+
Map<String, Object> gitInfo = (Map<String, Object>) git;
111+
assertThat(gitInfo).containsOnlyKeys("branch", "commit", "foo");
112+
assertThat(gitInfo.get("foo")).isEqualTo("bar");
113+
});
101114
}
102115

103116
@Test
104117
void customGitInfoContributor() {
105-
load(CustomGitInfoContributorConfiguration.class);
106-
assertThat(this.context.getBean(GitInfoContributor.class))
107-
.isSameAs(this.context.getBean("customGitInfoContributor"));
118+
this.contextRunner.withUserConfiguration(CustomGitInfoContributorConfiguration.class).run((context) -> {
119+
assertThat(context).hasSingleBean(GitInfoContributor.class);
120+
assertThat(context.getBean(GitInfoContributor.class)).isSameAs(context.getBean("customGitInfoContributor"));
121+
});
108122
}
109123

110124
@SuppressWarnings("unchecked")
111125
@Test
112126
void buildProperties() {
113-
load(BuildPropertiesConfiguration.class);
114-
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
115-
assertThat(beans).containsKeys("buildInfoContributor");
116-
Map<String, Object> content = invokeContributor(
117-
this.context.getBean("buildInfoContributor", InfoContributor.class));
118-
Object build = content.get("build");
119-
assertThat(build).isInstanceOf(Map.class);
120-
Map<String, Object> buildInfo = (Map<String, Object>) build;
121-
assertThat(buildInfo).containsOnlyKeys("group", "artifact", "foo");
122-
assertThat(buildInfo.get("foo")).isEqualTo("bar");
127+
this.contextRunner.withUserConfiguration(BuildPropertiesConfiguration.class).run((context) -> {
128+
assertThat(context).hasSingleBean(BuildInfoContributor.class);
129+
Map<String, Object> content = invokeContributor(context.getBean(BuildInfoContributor.class));
130+
Object build = content.get("build");
131+
assertThat(build).isInstanceOf(Map.class);
132+
Map<String, Object> buildInfo = (Map<String, Object>) build;
133+
assertThat(buildInfo).containsOnlyKeys("group", "artifact", "foo");
134+
assertThat(buildInfo.get("foo")).isEqualTo("bar");
135+
});
123136
}
124137

125138
@Test
126139
void customBuildInfoContributor() {
127-
load(CustomBuildInfoContributorConfiguration.class);
128-
assertThat(this.context.getBean(BuildInfoContributor.class))
129-
.isSameAs(this.context.getBean("customBuildInfoContributor"));
140+
this.contextRunner.withUserConfiguration(CustomBuildInfoContributorConfiguration.class).run((context) -> {
141+
assertThat(context).hasSingleBean(BuildInfoContributor.class);
142+
assertThat(context.getBean(BuildInfoContributor.class))
143+
.isSameAs(context.getBean("customBuildInfoContributor"));
144+
});
145+
}
146+
147+
@Test
148+
void javaInfoContributor() {
149+
this.contextRunner.run((context) -> {
150+
assertThat(context).hasSingleBean(JavaInfoContributor.class);
151+
Map<String, Object> content = invokeContributor(context.getBean(JavaInfoContributor.class));
152+
assertThat(content).containsKey("java");
153+
assertThat(content.get("java")).isInstanceOf(JavaInfo.class);
154+
});
130155
}
131156

132157
private Map<String, Object> invokeContributor(InfoContributor contributor) {
@@ -135,21 +160,6 @@ private Map<String, Object> invokeContributor(InfoContributor contributor) {
135160
return builder.build().getDetails();
136161
}
137162

138-
private void load(String... environment) {
139-
load(null, environment);
140-
}
141-
142-
private void load(Class<?> config, String... environment) {
143-
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
144-
if (config != null) {
145-
context.register(config);
146-
}
147-
context.register(InfoContributorAutoConfiguration.class);
148-
TestPropertyValues.of(environment).applyTo(context);
149-
context.refresh();
150-
this.context = context;
151-
}
152-
153163
@Configuration(proxyBeanMethods = false)
154164
static class GitPropertiesConfiguration {
155165

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2012-2021 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.info;
18+
19+
import org.springframework.boot.actuate.info.Info.Builder;
20+
import org.springframework.boot.info.JavaInfo;
21+
22+
/**
23+
* An {@link InfoContributor} that exposes {@link JavaInfo}.
24+
*
25+
* @author Jonatan Ivanov
26+
* @since 2.6.0
27+
*/
28+
public class JavaInfoContributor implements InfoContributor {
29+
30+
private final JavaInfo javaInfo;
31+
32+
public JavaInfoContributor() {
33+
this.javaInfo = new JavaInfo();
34+
}
35+
36+
@Override
37+
public void contribute(Builder builder) {
38+
builder.withDetail("java", this.javaInfo);
39+
}
40+
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2012-2021 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.info;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import org.springframework.boot.info.JavaInfo;
22+
23+
import static org.assertj.core.api.Assertions.assertThat;
24+
25+
/**
26+
* Tests for {@link JavaInfoContributor}
27+
*
28+
* @author Jonatan Ivanov
29+
*/
30+
class JavaInfoContributorTests {
31+
32+
@Test
33+
void javaInfoShouldBeAdded() {
34+
JavaInfoContributor javaInfoContributor = new JavaInfoContributor();
35+
Info.Builder builder = new Info.Builder();
36+
javaInfoContributor.contribute(builder);
37+
Info info = builder.build();
38+
assertThat(info.getDetails().get("java")).isInstanceOf(JavaInfo.class);
39+
}
40+
41+
}

spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/endpoints.adoc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,9 @@ When appropriate, Spring auto-configures the following `InfoContributor` beans:
11571157

11581158
| {spring-boot-actuator-module-code}/info/BuildInfoContributor.java[`BuildInfoContributor`]
11591159
| Exposes build information if a `META-INF/build-info.properties` file is available.
1160+
1161+
| {spring-boot-actuator-module-code}/info/JavaInfoContributor.java[`JavaInfoContributor`]
1162+
| Exposes Java runtime information under the `java` key.
11601163
|===
11611164

11621165
TIP: You can disable them all by setting the configprop:management.info.defaults.enabled[] property.
@@ -1240,6 +1243,12 @@ See "<<howto#howto.build.generate-info,how to generate build information>>" for
12401243

12411244

12421245

1246+
[[actuator.endpoints.info.java-information]]
1247+
==== Java Information
1248+
The `info` endpoint publishes information about your Java runtime environment, see {spring-boot-module-api}/info/JavaInfo.html[`JavaInfo`] for more details.
1249+
1250+
1251+
12431252
[[actuator.endpoints.info.writing-custom-info-contributors]]
12441253
==== Writing Custom InfoContributors
12451254
To provide custom application information, you can register Spring beans that implement the {spring-boot-actuator-module-code}/info/InfoContributor.java[`InfoContributor`] interface.

0 commit comments

Comments
 (0)