Add an option to log banner rather than printing it to standard out

This commit adds the option to output the banner using the logger
instead of standard out. Rather than taking a boolean
spring.main.show-banner is now configured using an enum. Three values
are supported:

 - LOG: the banner is logged
 - CONSOLE: the banner is printed to standard out (previously true)
 - OFF: the banner is switched off (previously false)

The default behavior remains unchanged; the banner will be printed to
standard out.

Closes gh-4022
See gh-4001
pull/4118/merge
“Jeremy 9 years ago committed by Andy Wilkinson
parent 031a8d5afa
commit 3090659971

@ -123,7 +123,7 @@ might have.
[source,properties,indent=0,subs="verbatim,quotes,attributes"] [source,properties,indent=0,subs="verbatim,quotes,attributes"]
---- ----
spring.main.web_environment=false spring.main.web_environment=false
spring.main.show_banner=false spring.main.show_banner=OFF
---- ----
and then the Spring Boot banner will not be printed on startup, and the application will and then the Spring Boot banner will not be printed on startup, and the application will
@ -139,7 +139,7 @@ consider this application
[source,java,indent=0] [source,java,indent=0]
---- ----
new SpringApplicationBuilder() new SpringApplicationBuilder()
.showBanner(false) .showBanner(Banner.Mode.OFF)
.sources(demo.MyApp.class) .sources(demo.MyApp.class)
.run(args); .run(args);
---- ----
@ -149,7 +149,7 @@ used with the following configuration:
[source,properties,indent=0,subs="verbatim,quotes,attributes"] [source,properties,indent=0,subs="verbatim,quotes,attributes"]
---- ----
spring.main.sources=com.acme.Config,com.acme.ExtraConfig spring.main.sources=com.acme.Config,com.acme.ExtraConfig
spring.main.show-banner=true spring.main.show-banner=CONSOLE
---- ----
The actual application will _now_ show the banner (as overridden by configuration) and use The actual application will _now_ show the banner (as overridden by configuration) and use

@ -124,7 +124,7 @@ For example:
[source,java,indent=0] [source,java,indent=0]
---- ----
new SpringApplicationBuilder() new SpringApplicationBuilder()
.showBanner(false) .showBanner(Banner.Mode.OFF)
.sources(Parent.class) .sources(Parent.class)
.child(Application.class) .child(Application.class)
.run(args); .run(args);

@ -25,6 +25,7 @@ import org.springframework.core.env.Environment;
* *
* @author Phillip Webb * @author Phillip Webb
* @author Michael Stummvoll * @author Michael Stummvoll
* @author Jeremy Rickard
* @since 1.2.0 * @since 1.2.0
*/ */
public interface Banner { public interface Banner {
@ -37,4 +38,25 @@ public interface Banner {
*/ */
void printBanner(Environment environment, Class<?> sourceClass, PrintStream out); void printBanner(Environment environment, Class<?> sourceClass, PrintStream out);
/**
* An enumeration of possible values for configuring the Banner.
*/
enum Mode {
/**
* Disable printing of the banner.
*/
OFF,
/**
* Print the banner to System.out.
*/
CONSOLE,
/**
* Print the banner to the log file.
*/
LOG
}
} }

@ -16,6 +16,8 @@
package org.springframework.boot; package org.springframework.boot;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.security.AccessControlException; import java.security.AccessControlException;
import java.util.ArrayList; import java.util.ArrayList;
@ -134,6 +136,7 @@ import org.springframework.web.context.support.StandardServletEnvironment;
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Christian Dupuis * @author Christian Dupuis
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Jeremy Rickard
* @see #run(Object, String[]) * @see #run(Object, String[])
* @see #run(Object[], String[]) * @see #run(Object[], String[])
* @see #SpringApplication(Object...) * @see #SpringApplication(Object...)
@ -179,7 +182,7 @@ public class SpringApplication {
private Class<?> mainApplicationClass; private Class<?> mainApplicationClass;
private boolean showBanner = true; private Banner.Mode showBanner = Banner.Mode.CONSOLE;
private boolean logStartupInfo = true; private boolean logStartupInfo = true;
@ -321,7 +324,7 @@ public class SpringApplication {
environment = convertToStandardEnvironment(environment); environment = convertToStandardEnvironment(environment);
} }
if (this.showBanner) { if (this.showBanner != Banner.Mode.OFF) {
printBanner(environment); printBanner(environment);
} }
@ -521,27 +524,37 @@ public class SpringApplication {
* banner.location=classpath:banner.txt, banner.charset=UTF-8. If the banner file does * banner.location=classpath:banner.txt, banner.charset=UTF-8. If the banner file does
* not exist or cannot be printed, a simple default is created. * not exist or cannot be printed, a simple default is created.
* @param environment the environment * @param environment the environment
* @see #setShowBanner(boolean) * @see #setShowBanner(org.springframework.boot.Banner.Mode)
*/ */
protected void printBanner(Environment environment) { protected void printBanner(Environment environment) {
Banner selectedBanner = selectBanner(environment);
if (this.showBanner == Banner.Mode.LOG) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
selectedBanner.printBanner(environment, this.mainApplicationClass,
new PrintStream(baos));
this.log.info(baos.toString());
}
else {
selectedBanner
.printBanner(environment, this.mainApplicationClass, System.out);
}
}
private Banner selectBanner(Environment environment) {
String location = environment.getProperty("banner.location", "banner.txt"); String location = environment.getProperty("banner.location", "banner.txt");
ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader
: new DefaultResourceLoader(getClassLoader()); : new DefaultResourceLoader(getClassLoader());
Resource resource = resourceLoader.getResource(location); Resource resource = resourceLoader.getResource(location);
if (resource.exists()) { if (resource.exists()) {
new ResourceBanner(resource).printBanner(environment, return new ResourceBanner(resource);
this.mainApplicationClass, System.out);
return;
} }
if (this.banner != null) { if (this.banner != null) {
this.banner.printBanner(environment, this.mainApplicationClass, System.out); return this.banner;
return;
} }
printDefaultBanner(); return DEFAULT_BANNER;
}
private void printDefaultBanner() {
DEFAULT_BANNER.printBanner(null, this.mainApplicationClass, System.out);
} }
/** /**
@ -840,11 +853,11 @@ public class SpringApplication {
/** /**
* Sets if the Spring banner should be displayed when the application runs. Defaults * Sets if the Spring banner should be displayed when the application runs. Defaults
* to {@code true}. * to {@code org.springframework.boot.Banner.Mode.CONSOLE}.
* @param showBanner if the banner should be shown * @param bannerMode if the banner should be shown in log or console, or turned off.
*/ */
public void setShowBanner(boolean showBanner) { public void setShowBanner(Banner.Mode bannerMode) {
this.showBanner = showBanner; this.showBanner = bannerMode;
} }
/** /**

@ -172,7 +172,7 @@ public class SpringApplicationBuilder {
web(false); web(false);
// Probably not interested in multiple banners // Probably not interested in multiple banners
showBanner(false); showBanner(Banner.Mode.OFF);
// Make sure sources get copied over // Make sure sources get copied over
this.application.setSources(this.sources); this.application.setSources(this.sources);
@ -311,7 +311,7 @@ public class SpringApplicationBuilder {
* @param showBanner the flag to set. Default true. * @param showBanner the flag to set. Default true.
* @return the current builder * @return the current builder
*/ */
public SpringApplicationBuilder showBanner(boolean showBanner) { public SpringApplicationBuilder showBanner(Banner.Mode showBanner) {
this.application.setShowBanner(showBanner); this.application.setShowBanner(showBanner);
return this; return this;
} }

@ -57,6 +57,14 @@ public class BannerTests {
assertThat(this.out.toString(), containsString(":: Spring Boot ::")); assertThat(this.out.toString(), containsString(":: Spring Boot ::"));
} }
@Test
public void testDefaultBannerInLog() throws Exception {
SpringApplication application = new SpringApplication(Config.class);
application.setWebEnvironment(false);
this.context = application.run();
assertThat(this.out.toString(), containsString(":: Spring Boot ::"));
}
@Test @Test
public void testCustomBanner() throws Exception { public void testCustomBanner() throws Exception {
SpringApplication application = new SpringApplication(Config.class); SpringApplication application = new SpringApplication(Config.class);

@ -76,7 +76,7 @@ public class SimpleMainTests {
private String[] getArgs(String... args) { private String[] getArgs(String... args) {
List<String> list = new ArrayList<String>(Arrays.asList( List<String> list = new ArrayList<String>(Arrays.asList(
"--spring.main.webEnvironment=false", "--spring.main.showBanner=false", "--spring.main.webEnvironment=false", "--spring.main.showBanner=OFF",
"--spring.main.registerShutdownHook=false")); "--spring.main.registerShutdownHook=false"));
if (args.length > 0) { if (args.length > 0) {
list.add("--spring.main.sources=" list.add("--spring.main.sources="

@ -82,6 +82,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
@ -95,6 +96,7 @@ import static org.mockito.Mockito.verify;
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Christian Dupuis * @author Christian Dupuis
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Jeremy Rickard
*/ */
public class SpringApplicationTests { public class SpringApplicationTests {
@ -164,7 +166,7 @@ public class SpringApplicationTests {
public void disableBanner() throws Exception { public void disableBanner() throws Exception {
SpringApplication application = spy(new SpringApplication(ExampleConfig.class)); SpringApplication application = spy(new SpringApplication(ExampleConfig.class));
application.setWebEnvironment(false); application.setWebEnvironment(false);
application.setShowBanner(false); application.setShowBanner(Banner.Mode.OFF);
this.context = application.run(); this.context = application.run();
verify(application, never()).printBanner((Environment) anyObject()); verify(application, never()).printBanner((Environment) anyObject());
} }
@ -173,7 +175,7 @@ public class SpringApplicationTests {
public void disableBannerViaProperty() throws Exception { public void disableBannerViaProperty() throws Exception {
SpringApplication application = spy(new SpringApplication(ExampleConfig.class)); SpringApplication application = spy(new SpringApplication(ExampleConfig.class));
application.setWebEnvironment(false); application.setWebEnvironment(false);
this.context = application.run("--spring.main.show_banner=false"); this.context = application.run("--spring.main.show_banner=OFF");
verify(application, never()).printBanner((Environment) anyObject()); verify(application, never()).printBanner((Environment) anyObject());
} }
@ -213,6 +215,24 @@ public class SpringApplicationTests {
containsString("The following profiles are active: myprofile")); containsString("The following profiles are active: myprofile"));
} }
@Test
public void enableBannerInLogViaProperty() throws Exception {
SpringApplication application = spy(new SpringApplication(ExampleConfig.class));
application.setWebEnvironment(false);
this.context = application.run("--spring.main.show_banner=LOG");
verify(application, atLeastOnce()).setShowBanner(Banner.Mode.LOG);
}
@Test
public void verifyBannerOutputContainsLogInfo() throws Exception {
SpringApplication application = spy(new SpringApplication(ExampleConfig.class));
application.setWebEnvironment(false);
application.run("--spring.main.show_banner=LOG",
"--banner.location=classpath:test-banner.txt");
verify(application, atLeastOnce()).setShowBanner(Banner.Mode.LOG);
assertThat(this.output.toString(), containsString("o.s.boot.SpringApplication"));
}
@Test @Test
public void customId() throws Exception { public void customId() throws Exception {
SpringApplication application = new SpringApplication(ExampleConfig.class); SpringApplication application = new SpringApplication(ExampleConfig.class);
@ -545,8 +565,8 @@ public class SpringApplicationTests {
TestSpringApplication application = new TestSpringApplication( TestSpringApplication application = new TestSpringApplication(
ExampleConfig.class); ExampleConfig.class);
application.setWebEnvironment(false); application.setWebEnvironment(false);
this.context = application.run("--spring.main.show_banner=false"); this.context = application.run("--spring.main.show_banner=OFF");
assertThat(application.getShowBanner(), is(false)); assertThat(application.getShowBanner(), is(Banner.Mode.OFF));
} }
@Test @Test
@ -713,7 +733,7 @@ public class SpringApplicationTests {
private boolean useMockLoader; private boolean useMockLoader;
private boolean showBanner; private Banner.Mode showBanner;
TestSpringApplication(Object... sources) { TestSpringApplication(Object... sources) {
super(sources); super(sources);
@ -744,12 +764,12 @@ public class SpringApplicationTests {
} }
@Override @Override
public void setShowBanner(boolean showBanner) { public void setShowBanner(Banner.Mode bannerMode) {
super.setShowBanner(showBanner); super.setShowBanner(bannerMode);
this.showBanner = showBanner; this.showBanner = bannerMode;
} }
public boolean getShowBanner() { public Banner.Mode getShowBanner() {
return this.showBanner; return this.showBanner;
} }

@ -34,6 +34,7 @@ import org.junit.After;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor.ConfigurationPropertySources; import org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor.ConfigurationPropertySources;
import org.springframework.boot.env.EnumerableCompositePropertySource; import org.springframework.boot.env.EnumerableCompositePropertySource;
@ -625,17 +626,17 @@ public class ConfigFileEnvironmentPostProcessorTests {
this.initializer.postProcessEnvironment(this.environment, this.application); this.initializer.postProcessEnvironment(this.environment, this.application);
Field field = ReflectionUtils.findField(SpringApplication.class, "showBanner"); Field field = ReflectionUtils.findField(SpringApplication.class, "showBanner");
field.setAccessible(true); field.setAccessible(true);
assertThat((Boolean) field.get(this.application), equalTo(false)); assertThat((Banner.Mode) field.get(this.application), equalTo(Banner.Mode.OFF));
} }
@Test @Test
public void bindsSystemPropertyToSpringApplication() throws Exception { public void bindsSystemPropertyToSpringApplication() throws Exception {
// gh-951 // gh-951
System.setProperty("spring.main.showBanner", "false"); System.setProperty("spring.main.showBanner", "OFF");
this.initializer.postProcessEnvironment(this.environment, this.application); this.initializer.postProcessEnvironment(this.environment, this.application);
Field field = ReflectionUtils.findField(SpringApplication.class, "showBanner"); Field field = ReflectionUtils.findField(SpringApplication.class, "showBanner");
field.setAccessible(true); field.setAccessible(true);
assertThat((Boolean) field.get(this.application), equalTo(false)); assertThat((Banner.Mode) field.get(this.application), equalTo(Banner.Mode.OFF));
} }
private static Matcher<? super ConfigurableEnvironment> containsPropertySource( private static Matcher<? super ConfigurableEnvironment> containsPropertySource(

@ -1 +1 @@
spring.main.show_banner=false spring.main.show_banner=OFF

Loading…
Cancel
Save