diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 58fabb5c473..b7af65f8a4c 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -43,6 +43,7 @@ content into your application; rather pick only the properties that you need. spring.main.sources= # sources (class name, package name or XML resource location) to include spring.main.web-environment= # detect by default spring.main.show-banner=true + spring.main.banner-mode=console # the mode used to display the banner (console, off, or log) spring.main....= # see class for all properties # AUTO-CONFIGURATION diff --git a/spring-boot-docs/src/main/asciidoc/howto.adoc b/spring-boot-docs/src/main/asciidoc/howto.adoc index 7031be4bf17..ed48010ecfd 100644 --- a/spring-boot-docs/src/main/asciidoc/howto.adoc +++ b/spring-boot-docs/src/main/asciidoc/howto.adoc @@ -123,7 +123,7 @@ might have. [source,properties,indent=0,subs="verbatim,quotes,attributes"] ---- spring.main.web_environment=false - spring.main.show_banner=false + spring.main.banner_mode=off ---- 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] ---- new SpringApplicationBuilder() - .showBanner(false) + .bannerMode(Banner.Mode.OFF) .sources(demo.MyApp.class) .run(args); ---- @@ -149,7 +149,7 @@ used with the following configuration: [source,properties,indent=0,subs="verbatim,quotes,attributes"] ---- spring.main.sources=com.acme.Config,com.acme.ExtraConfig - spring.main.show-banner=true + spring.main.banner_mode=console ---- The actual application will _now_ show the banner (as overridden by configuration) and use diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index eebc128cac2..43c6bf5b9cb 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -93,7 +93,7 @@ instance and customize it. For example, to turn off the banner you would write: ---- public static void main(String[] args) { SpringApplication app = new SpringApplication(MySpringConfiguration.class); - app.setShowBanner(false); + app.setBannerMode(Banner.Mode.OFF); app.run(args); } ---- @@ -124,7 +124,7 @@ For example: [source,java,indent=0] ---- new SpringApplicationBuilder() - .showBanner(false) + .bannerMode(Banner.Mode.OFF) .sources(Parent.class) .child(Application.class) .run(args); diff --git a/spring-boot/src/main/java/org/springframework/boot/Banner.java b/spring-boot/src/main/java/org/springframework/boot/Banner.java index 2b7f6294726..e8f9c857155 100644 --- a/spring-boot/src/main/java/org/springframework/boot/Banner.java +++ b/spring-boot/src/main/java/org/springframework/boot/Banner.java @@ -25,6 +25,7 @@ import org.springframework.core.env.Environment; * * @author Phillip Webb * @author Michael Stummvoll + * @author Jeremy Rickard * @since 1.2.0 */ public interface Banner { @@ -37,4 +38,25 @@ public interface Banner { */ 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 + } + } diff --git a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index e9337594d32..fce9d4191c7 100644 --- a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -16,6 +16,9 @@ package org.springframework.boot; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; import java.lang.reflect.Constructor; import java.security.AccessControlException; import java.util.ArrayList; @@ -134,6 +137,7 @@ import org.springframework.web.context.support.StandardServletEnvironment; * @author Andy Wilkinson * @author Christian Dupuis * @author Stephane Nicoll + * @author Jeremy Rickard * @see #run(Object, String[]) * @see #run(Object[], String[]) * @see #SpringApplication(Object...) @@ -179,7 +183,7 @@ public class SpringApplication { private Class mainApplicationClass; - private boolean showBanner = true; + private Banner.Mode bannerMode = Banner.Mode.CONSOLE; private boolean logStartupInfo = true; @@ -321,7 +325,7 @@ public class SpringApplication { environment = convertToStandardEnvironment(environment); } - if (this.showBanner) { + if (this.bannerMode != Banner.Mode.OFF) { printBanner(environment); } @@ -521,27 +525,47 @@ public class SpringApplication { * 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. * @param environment the environment - * @see #setShowBanner(boolean) + * @see #setBannerMode */ protected void printBanner(Environment environment) { + + Banner selectedBanner = selectBanner(environment); + + if (this.bannerMode == Banner.Mode.LOG) { + try { + this.log.info(createStringFromBanner(selectedBanner, environment)); + } + catch (UnsupportedEncodingException ex) { + this.log.warn("Failed to create String for banner", ex); + } + } + else { + selectedBanner.printBanner(environment, this.mainApplicationClass, + System.out); + } + } + + private Banner selectBanner(Environment environment) { String location = environment.getProperty("banner.location", "banner.txt"); ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader : new DefaultResourceLoader(getClassLoader()); Resource resource = resourceLoader.getResource(location); + if (resource.exists()) { - new ResourceBanner(resource).printBanner(environment, - this.mainApplicationClass, System.out); - return; + return new ResourceBanner(resource); } if (this.banner != null) { - this.banner.printBanner(environment, this.mainApplicationClass, System.out); - return; + return this.banner; } - printDefaultBanner(); + return DEFAULT_BANNER; } - private void printDefaultBanner() { - DEFAULT_BANNER.printBanner(null, this.mainApplicationClass, System.out); + private String createStringFromBanner(Banner banner, Environment environment) + throws UnsupportedEncodingException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + banner.printBanner(environment, this.mainApplicationClass, new PrintStream(baos)); + String charset = environment.getProperty("banner.charset", "UTF-8"); + return baos.toString(charset); } /** @@ -842,9 +866,20 @@ public class SpringApplication { * Sets if the Spring banner should be displayed when the application runs. Defaults * to {@code true}. * @param showBanner if the banner should be shown + * @deprecated since 1.3.0 in favor of {@link #setBannerMode} */ + @Deprecated public void setShowBanner(boolean showBanner) { - this.showBanner = showBanner; + setBannerMode(showBanner ? Banner.Mode.CONSOLE : Banner.Mode.OFF); + } + + /** + * Sets the mode used to display the banner when the application runs. Defaults to + * {@code Banner.Mode.CONSOLE}. + * @param bannerMode the mode used to display the banner + */ + public void setBannerMode(Banner.Mode bannerMode) { + this.bannerMode = bannerMode; } /** diff --git a/spring-boot/src/main/java/org/springframework/boot/builder/SpringApplicationBuilder.java b/spring-boot/src/main/java/org/springframework/boot/builder/SpringApplicationBuilder.java index 55c4f4b5fe5..005eda5d3cc 100644 --- a/spring-boot/src/main/java/org/springframework/boot/builder/SpringApplicationBuilder.java +++ b/spring-boot/src/main/java/org/springframework/boot/builder/SpringApplicationBuilder.java @@ -172,7 +172,7 @@ public class SpringApplicationBuilder { web(false); // Probably not interested in multiple banners - showBanner(false); + bannerMode(Banner.Mode.OFF); // Make sure sources get copied over this.application.setSources(this.sources); @@ -310,12 +310,19 @@ public class SpringApplicationBuilder { * Flag to indicate the startup banner should be printed. * @param showBanner the flag to set. Default true. * @return the current builder + * @deprecated Since 1.3.0 in favor of {@link #bannerMode} */ + @Deprecated public SpringApplicationBuilder showBanner(boolean showBanner) { this.application.setShowBanner(showBanner); return this; } + public SpringApplicationBuilder bannerMode(Banner.Mode bannerMode) { + this.application.setBannerMode(bannerMode); + return this; + } + /** * Sets if the application is headless and should not instantiate AWT. Defaults to * {@code true} to prevent java icons appearing. diff --git a/spring-boot/src/test/java/org/springframework/boot/BannerTests.java b/spring-boot/src/test/java/org/springframework/boot/BannerTests.java index 0d3d05ee5b8..346db7a31b2 100644 --- a/spring-boot/src/test/java/org/springframework/boot/BannerTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/BannerTests.java @@ -57,6 +57,14 @@ public class BannerTests { 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 public void testCustomBanner() throws Exception { SpringApplication application = new SpringApplication(Config.class); diff --git a/spring-boot/src/test/java/org/springframework/boot/SimpleMainTests.java b/spring-boot/src/test/java/org/springframework/boot/SimpleMainTests.java index 93f4cc4da5d..60b46ffcb38 100644 --- a/spring-boot/src/test/java/org/springframework/boot/SimpleMainTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/SimpleMainTests.java @@ -76,7 +76,7 @@ public class SimpleMainTests { private String[] getArgs(String... args) { List list = new ArrayList(Arrays.asList( - "--spring.main.webEnvironment=false", "--spring.main.showBanner=false", + "--spring.main.webEnvironment=false", "--spring.main.showBanner=OFF", "--spring.main.registerShutdownHook=false")); if (args.length > 0) { list.add("--spring.main.sources=" diff --git a/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java b/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java index 8e068643d8a..d446a04abaa 100644 --- a/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java @@ -82,6 +82,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.anyObject; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -95,6 +96,7 @@ import static org.mockito.Mockito.verify; * @author Andy Wilkinson * @author Christian Dupuis * @author Stephane Nicoll + * @author Jeremy Rickard */ public class SpringApplicationTests { @@ -161,7 +163,17 @@ public class SpringApplicationTests { } @Test - public void disableBanner() throws Exception { + public void disableBannerWithMode() throws Exception { + SpringApplication application = spy(new SpringApplication(ExampleConfig.class)); + application.setWebEnvironment(false); + application.setBannerMode(Banner.Mode.OFF); + this.context = application.run(); + verify(application, never()).printBanner((Environment) anyObject()); + } + + @SuppressWarnings("deprecation") + @Test + public void disableBannerWithBoolean() throws Exception { SpringApplication application = spy(new SpringApplication(ExampleConfig.class)); application.setWebEnvironment(false); application.setShowBanner(false); @@ -170,13 +182,21 @@ public class SpringApplicationTests { } @Test - public void disableBannerViaProperty() throws Exception { + public void disableBannerViaShowBannerProperty() throws Exception { SpringApplication application = spy(new SpringApplication(ExampleConfig.class)); application.setWebEnvironment(false); this.context = application.run("--spring.main.show_banner=false"); verify(application, never()).printBanner((Environment) anyObject()); } + @Test + public void disableBannerViaBannerModeProperty() throws Exception { + SpringApplication application = spy(new SpringApplication(ExampleConfig.class)); + application.setWebEnvironment(false); + this.context = application.run("--spring.main.banner-mode=off"); + verify(application, never()).printBanner((Environment) anyObject()); + } + @Test public void customBanner() throws Exception { SpringApplication application = spy(new SpringApplication(ExampleConfig.class)); @@ -213,6 +233,15 @@ public class SpringApplicationTests { 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.banner-mode=log"); + verify(application, atLeastOnce()).setBannerMode(Banner.Mode.LOG); + assertThat(this.output.toString(), containsString("o.s.boot.SpringApplication")); + } + @Test public void customId() throws Exception { SpringApplication application = new SpringApplication(ExampleConfig.class); @@ -545,8 +574,8 @@ public class SpringApplicationTests { TestSpringApplication application = new TestSpringApplication( ExampleConfig.class); application.setWebEnvironment(false); - this.context = application.run("--spring.main.show_banner=false"); - assertThat(application.getShowBanner(), is(false)); + this.context = application.run("--spring.main.banner-mode=OFF"); + assertThat(application.getBannerMode(), is(Banner.Mode.OFF)); } @Test @@ -713,7 +742,7 @@ public class SpringApplicationTests { private boolean useMockLoader; - private boolean showBanner; + private Banner.Mode bannerMode; TestSpringApplication(Object... sources) { super(sources); @@ -744,13 +773,13 @@ public class SpringApplicationTests { } @Override - public void setShowBanner(boolean showBanner) { - super.setShowBanner(showBanner); - this.showBanner = showBanner; + public void setBannerMode(Banner.Mode bannerMode) { + super.setBannerMode(bannerMode); + this.bannerMode = bannerMode; } - public boolean getShowBanner() { - return this.showBanner; + public Banner.Mode getBannerMode() { + return this.bannerMode; } } diff --git a/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileEnvironmentPostProcessorTests.java b/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileEnvironmentPostProcessorTests.java index 2d9d4b8b6b3..c9ae2bd971c 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileEnvironmentPostProcessorTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileEnvironmentPostProcessorTests.java @@ -34,6 +34,7 @@ import org.junit.After; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; import org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor.ConfigurationPropertySources; import org.springframework.boot.env.EnumerableCompositePropertySource; @@ -87,7 +88,7 @@ public class ConfigFileEnvironmentPostProcessorTests { } System.clearProperty("the.property"); System.clearProperty("spring.config.location"); - System.clearProperty("spring.main.showBanner"); + System.clearProperty("spring.main.banner-mode"); } @Test @@ -623,19 +624,19 @@ public class ConfigFileEnvironmentPostProcessorTests { // gh-346 this.initializer.setSearchNames("bindtoapplication"); this.initializer.postProcessEnvironment(this.environment, this.application); - Field field = ReflectionUtils.findField(SpringApplication.class, "showBanner"); + Field field = ReflectionUtils.findField(SpringApplication.class, "bannerMode"); field.setAccessible(true); - assertThat((Boolean) field.get(this.application), equalTo(false)); + assertThat((Banner.Mode) field.get(this.application), equalTo(Banner.Mode.OFF)); } @Test public void bindsSystemPropertyToSpringApplication() throws Exception { // gh-951 - System.setProperty("spring.main.showBanner", "false"); + System.setProperty("spring.main.banner-mode", "off"); this.initializer.postProcessEnvironment(this.environment, this.application); - Field field = ReflectionUtils.findField(SpringApplication.class, "showBanner"); + Field field = ReflectionUtils.findField(SpringApplication.class, "bannerMode"); 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 containsPropertySource( diff --git a/spring-boot/src/test/resources/bindtoapplication.properties b/spring-boot/src/test/resources/bindtoapplication.properties index 322672defd4..33406d213f8 100644 --- a/spring-boot/src/test/resources/bindtoapplication.properties +++ b/spring-boot/src/test/resources/bindtoapplication.properties @@ -1 +1 @@ -spring.main.show_banner=false +spring.main.banner-mode=off