Skip to content

Commit 874ee99

Browse files
committed
Improve handling of default values when printing the banner
Previously, default values for the following properties did not work: - application.title - application.formatted-version - application.version - spring-boot.formatted-version - spring-boot.version Instead of the default value, an empty string was used instead. For example, ${application.title:Title} would be replaced with "" rather than "Title" when the application title was unavailable. This commit improves the ResourceBanner so that a placeholder's default value is used. An empty string will still be used when no default value is provided. For example, ${application.title} will be replaced with "". As before, custom properties that are not well-known will not be replaced at all. For example ${custom.property} will remain as-is in the printed banner when the custom.property has not been set. Fixes gh-44137
1 parent f9540c0 commit 874ee99

File tree

2 files changed

+59
-23
lines changed

2 files changed

+59
-23
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ResourceBanner.java

+32-20
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 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.
@@ -85,22 +85,34 @@ public void printBanner(Environment environment, Class<?> sourceClass, PrintStre
8585
* @return a mutable list of property resolvers
8686
*/
8787
protected List<PropertyResolver> getPropertyResolvers(Environment environment, Class<?> sourceClass) {
88-
MutablePropertySources sources = new MutablePropertySources();
89-
if (environment instanceof ConfigurableEnvironment configurableEnvironment) {
90-
configurableEnvironment.getPropertySources().forEach(sources::addLast);
91-
}
92-
sources.addLast(getTitleSource(sourceClass));
93-
sources.addLast(getAnsiSource());
94-
sources.addLast(getVersionSource(sourceClass));
9588
List<PropertyResolver> resolvers = new ArrayList<>();
96-
resolvers.add(new PropertySourcesPropertyResolver(sources));
89+
resolvers.add(new PropertySourcesPropertyResolver(createNullDefaultSources(environment, sourceClass)));
90+
resolvers.add(new PropertySourcesPropertyResolver(createEmptyDefaultSources(sourceClass)));
9791
return resolvers;
9892
}
9993

100-
private MapPropertySource getTitleSource(Class<?> sourceClass) {
94+
private MutablePropertySources createNullDefaultSources(Environment environment, Class<?> sourceClass) {
95+
MutablePropertySources nullDefaultSources = new MutablePropertySources();
96+
if (environment instanceof ConfigurableEnvironment configurableEnvironment) {
97+
configurableEnvironment.getPropertySources().forEach(nullDefaultSources::addLast);
98+
}
99+
nullDefaultSources.addLast(getTitleSource(sourceClass, null));
100+
nullDefaultSources.addLast(getAnsiSource());
101+
nullDefaultSources.addLast(getVersionSource(sourceClass, null));
102+
return nullDefaultSources;
103+
}
104+
105+
private MutablePropertySources createEmptyDefaultSources(Class<?> sourceClass) {
106+
MutablePropertySources emptyDefaultSources = new MutablePropertySources();
107+
emptyDefaultSources.addLast(getTitleSource(sourceClass, ""));
108+
emptyDefaultSources.addLast(getVersionSource(sourceClass, ""));
109+
return emptyDefaultSources;
110+
}
111+
112+
private MapPropertySource getTitleSource(Class<?> sourceClass, String defaultValue) {
101113
String applicationTitle = getApplicationTitle(sourceClass);
102114
Map<String, Object> titleMap = Collections.singletonMap("application.title",
103-
(applicationTitle != null) ? applicationTitle : "");
115+
(applicationTitle != null) ? applicationTitle : defaultValue);
104116
return new MapPropertySource("title", titleMap);
105117
}
106118

@@ -119,18 +131,18 @@ private AnsiPropertySource getAnsiSource() {
119131
return new AnsiPropertySource("ansi", true);
120132
}
121133

122-
private MapPropertySource getVersionSource(Class<?> sourceClass) {
123-
return new MapPropertySource("version", getVersionsMap(sourceClass));
134+
private MapPropertySource getVersionSource(Class<?> sourceClass, String defaultValue) {
135+
return new MapPropertySource("version", getVersionsMap(sourceClass, defaultValue));
124136
}
125137

126-
private Map<String, Object> getVersionsMap(Class<?> sourceClass) {
138+
private Map<String, Object> getVersionsMap(Class<?> sourceClass, String defaultValue) {
127139
String appVersion = getApplicationVersion(sourceClass);
128140
String bootVersion = getBootVersion();
129141
Map<String, Object> versions = new HashMap<>();
130-
versions.put("application.version", getVersionString(appVersion, false));
131-
versions.put("spring-boot.version", getVersionString(bootVersion, false));
132-
versions.put("application.formatted-version", getVersionString(appVersion, true));
133-
versions.put("spring-boot.formatted-version", getVersionString(bootVersion, true));
142+
versions.put("application.version", getVersionString(appVersion, false, defaultValue));
143+
versions.put("spring-boot.version", getVersionString(bootVersion, false, defaultValue));
144+
versions.put("application.formatted-version", getVersionString(appVersion, true, defaultValue));
145+
versions.put("spring-boot.formatted-version", getVersionString(bootVersion, true, defaultValue));
134146
return versions;
135147
}
136148

@@ -143,9 +155,9 @@ protected String getBootVersion() {
143155
return SpringBootVersion.getVersion();
144156
}
145157

146-
private String getVersionString(String version, boolean format) {
158+
private String getVersionString(String version, boolean format, String fallback) {
147159
if (version == null) {
148-
return "";
160+
return fallback;
149161
}
150162
return format ? " (v" + version + ")" : version;
151163
}

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ResourceBannerTests.java

+27-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2025 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.
@@ -69,6 +69,14 @@ void renderWithoutVersions() {
6969
assertThat(banner).startsWith("banner 1 ");
7070
}
7171

72+
@Test
73+
void renderWithoutVersionsWithDefaultValues() {
74+
Resource resource = new ByteArrayResource(
75+
"banner ${a} ${spring-boot.version:X.Y.Z} ${application.version:A.B.C}".getBytes());
76+
String banner = printBanner(resource, null, null, null);
77+
assertThat(banner).startsWith("banner 1 X.Y.Z A.B.C");
78+
}
79+
7280
@Test
7381
void renderFormattedVersions() {
7482
Resource resource = new ByteArrayResource(
@@ -80,9 +88,18 @@ void renderFormattedVersions() {
8088
@Test
8189
void renderWithoutFormattedVersions() {
8290
Resource resource = new ByteArrayResource(
83-
"banner ${a}${spring-boot.formatted-version}${application.formatted-version}".getBytes());
91+
"banner ${a} ${spring-boot.formatted-version} ${application.formatted-version}".getBytes());
8492
String banner = printBanner(resource, null, null, null);
85-
assertThat(banner).startsWith("banner 1");
93+
assertThat(banner).startsWith("banner 1 ");
94+
}
95+
96+
@Test
97+
void renderWithoutFormattedVersionsWithDefaultValues() {
98+
Resource resource = new ByteArrayResource(
99+
"banner ${a} ${spring-boot.formatted-version:(vX.Y.Z)} ${application.formatted-version:(vA.B.C)}"
100+
.getBytes());
101+
String banner = printBanner(resource, null, null, null);
102+
assertThat(banner).startsWith("banner 1 (vX.Y.Z) (vA.B.C)");
86103
}
87104

88105
@Test
@@ -131,6 +148,13 @@ void renderWithoutTitle() {
131148
assertThat(banner).startsWith("banner 1");
132149
}
133150

151+
@Test
152+
void renderWithoutTitleWithDefaultValue() {
153+
Resource resource = new ByteArrayResource("banner ${application.title:Default Title} ${a}".getBytes());
154+
String banner = printBanner(resource, null, null, null);
155+
assertThat(banner).startsWith("banner Default Title 1");
156+
}
157+
134158
@Test
135159
void renderWithDefaultValues() {
136160
Resource resource = new ByteArrayResource(

0 commit comments

Comments
 (0)