diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.java index 3bd237dcd9..1d3308f2e3 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.java @@ -75,6 +75,7 @@ public class MessageSourceAutoConfiguration { messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale()); messageSource.setCacheSeconds(properties.getCacheSeconds()); messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat()); + messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage()); return messageSource; } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceProperties.java index b4a1fd94ba..456be83100 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceProperties.java @@ -22,6 +22,7 @@ import java.nio.charset.Charset; * Configuration properties for Message Source. * * @author Stephane Nicoll + * @author Kedar Joshi * @since 2.0.0 */ public class MessageSourceProperties { @@ -57,6 +58,12 @@ public class MessageSourceProperties { */ private boolean alwaysUseMessageFormat = false; + /** + * Set whether to use the message code as default message instead of throwing a + * "NoSuchMessageException". Recommended during development only. + */ + private boolean useCodeAsDefaultMessage = false; + public String getBasename() { return this.basename; } @@ -97,4 +104,12 @@ public class MessageSourceProperties { this.alwaysUseMessageFormat = alwaysUseMessageFormat; } + public boolean isUseCodeAsDefaultMessage() { + return this.useCodeAsDefaultMessage; + } + + public void setUseCodeAsDefaultMessage(final boolean useCodeAsDefaultMessage) { + this.useCodeAsDefaultMessage = useCodeAsDefaultMessage; + } + } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfigurationTests.java index 19501894d5..fae2645057 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfigurationTests.java @@ -18,17 +18,15 @@ package org.springframework.boot.autoconfigure.context; import java.util.Locale; -import org.junit.After; import org.junit.Ignore; import org.junit.Test; import org.springframework.beans.DirectFieldAccessor; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceResolvable; import org.springframework.context.NoSuchMessageException; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; @@ -41,95 +39,93 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Dave Syer * @author Eddú Meléndez * @author Stephane Nicoll + * @author Kedar Joshi */ public class MessageSourceAutoConfigurationTests { - private AnnotationConfigApplicationContext context; + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of( + MessageSourceAutoConfiguration.class)); - @After - public void closeContext() { - if (this.context != null) { - this.context.close(); - } + @Test + public void testDefaultMessageSource() { + this.contextRunner.run((context) -> + assertThat(context.getMessage("foo", null, "Foo message", Locale.UK)) + .isEqualTo("Foo message")); } @Test - public void testDefaultMessageSource() throws Exception { - load(); - assertThat(this.context.getMessage("foo", null, "Foo message", Locale.UK)) - .isEqualTo("Foo message"); + public void testMessageSourceCreated() { + this.contextRunner.withPropertyValues("spring.messages.basename:test/messages") + .run((context) -> assertThat(context.getMessage( + "foo", null, "Foo message", Locale.UK)).isEqualTo("bar")); } @Test - public void testMessageSourceCreated() throws Exception { - load("spring.messages.basename:test/messages"); - assertThat(this.context.getMessage("foo", null, "Foo message", Locale.UK)) - .isEqualTo("bar"); + public void testEncodingWorks() { + this.contextRunner.withPropertyValues("spring.messages.basename:test/swedish") + .run((context) -> assertThat(context.getMessage( + "foo", null, "Foo message", Locale.UK)).isEqualTo( + "Some text with some swedish öäå!")); } @Test - public void testEncodingWorks() throws Exception { - load("spring.messages.basename:test/swedish"); - assertThat(this.context.getMessage("foo", null, "Foo message", Locale.UK)) - .isEqualTo("Some text with some swedish öäå!"); + public void testMultipleMessageSourceCreated() { + this.contextRunner.withPropertyValues( + "spring.messages.basename:test/messages,test/messages2").run((context) -> { + assertThat(context.getMessage("foo", null, "Foo message", Locale.UK)) + .isEqualTo("bar"); + assertThat(context.getMessage("foo-foo", null, "Foo-Foo message", Locale.UK)) + .isEqualTo("bar-bar"); + }); } @Test - public void testMultipleMessageSourceCreated() throws Exception { - load("spring.messages.basename:test/messages,test/messages2"); - assertThat(this.context.getMessage("foo", null, "Foo message", Locale.UK)) - .isEqualTo("bar"); - assertThat(this.context.getMessage("foo-foo", null, "Foo-Foo message", Locale.UK)) - .isEqualTo("bar-bar"); - } - - @Test - public void testBadEncoding() throws Exception { - load("spring.messages.encoding:rubbish"); - // Bad encoding just means the messages are ignored - assertThat(this.context.getMessage("foo", null, "blah", Locale.UK)) - .isEqualTo("blah"); + public void testBadEncoding() { + this.contextRunner.withPropertyValues("spring.messages.encoding:rubbish") + .run((context) -> { + // Bad encoding just means the messages are ignored + assertThat(context.getMessage("foo", null, "blah", Locale.UK)) + .isEqualTo("blah"); + }); } @Test @Ignore("Expected to fail per gh-1075") - public void testMessageSourceFromPropertySourceAnnotation() throws Exception { - this.context = new AnnotationConfigApplicationContext(); - this.context.register(Config.class, MessageSourceAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class); - this.context.refresh(); - assertThat(this.context.getMessage("foo", null, "Foo message", Locale.UK)) - .isEqualTo("bar"); + public void testMessageSourceFromPropertySourceAnnotation() { + this.contextRunner.withUserConfiguration(Config.class).run((context) -> + assertThat(context.getMessage("foo", null, "Foo message", Locale.UK)) + .isEqualTo("bar")); } @Test - public void testFallbackDefault() throws Exception { - load("spring.messages.basename:test/messages"); - assertThat(isFallbackToSystemLocale(this.context.getBean(MessageSource.class))) - .isTrue(); + public void testFallbackDefault() { + this.contextRunner.withPropertyValues("spring.messages.basename:test/messages") + .run((context) -> assertThat(isFallbackToSystemLocale( + context.getBean(MessageSource.class))).isTrue()); } @Test - public void testFallbackTurnOff() throws Exception { - load("spring.messages.basename:test/messages", - "spring.messages.fallback-to-system-locale:false"); - assertThat(isFallbackToSystemLocale(this.context.getBean(MessageSource.class))) - .isFalse(); + public void testFallbackTurnOff() { + this.contextRunner.withPropertyValues("spring.messages.basename:test/messages", + "spring.messages.fallback-to-system-locale:false").run((context) -> + assertThat(isFallbackToSystemLocale(context.getBean(MessageSource.class))) + .isFalse()); } @Test - public void testFormatMessageDefault() throws Exception { - load("spring.messages.basename:test/messages"); - assertThat(isAlwaysUseMessageFormat(this.context.getBean(MessageSource.class))) - .isFalse(); + public void testFormatMessageDefault() { + this.contextRunner.withPropertyValues("spring.messages.basename:test/messages") + .run((context) -> assertThat(isAlwaysUseMessageFormat( + context.getBean(MessageSource.class))).isFalse()); } @Test public void testFormatMessageOn() throws Exception { - load("spring.messages.basename:test/messages", - "spring.messages.always-use-message-format:true"); - assertThat(isAlwaysUseMessageFormat(this.context.getBean(MessageSource.class))) - .isTrue(); + this.contextRunner.withPropertyValues("spring.messages.basename:test/messages", + "spring.messages.always-use-message-format:true").run((context) -> + assertThat(isAlwaysUseMessageFormat(context.getBean(MessageSource.class))) + .isTrue()); } private boolean isFallbackToSystemLocale(MessageSource messageSource) { @@ -142,38 +138,41 @@ public class MessageSourceAutoConfigurationTests { .getPropertyValue("alwaysUseMessageFormat"); } + @Test + public void testUseCodeAsDefaultMessageDefault() { + this.contextRunner.withPropertyValues("spring.messages.basename:test/messages") + .run((context) -> assertThat(isUseCodeAsDefaultMessage( + context.getBean(MessageSource.class))).isFalse()); + } + + @Test + public void testUseCodeAsDefaultMessageOn() { + this.contextRunner.withPropertyValues("spring.messages.basename:test/messages", + "spring.messages.use-code-as-default-message:true").run((context) -> + assertThat(isUseCodeAsDefaultMessage( + context.getBean(MessageSource.class))).isTrue()); + } + + private boolean isUseCodeAsDefaultMessage(MessageSource messageSource) { + return (boolean) new DirectFieldAccessor(messageSource) + .getPropertyValue("useCodeAsDefaultMessage"); + } + @Test public void existingMessageSourceIsPreferred() { - this.context = new AnnotationConfigApplicationContext(); - this.context.register(CustomMessageSource.class, - MessageSourceAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class); - this.context.refresh(); - assertThat(this.context.getMessage("foo", null, null, null)).isEqualTo("foo"); + this.contextRunner.withUserConfiguration(CustomMessageSource.class) + .run((context) -> assertThat(context.getMessage("foo", null, null, null)) + .isEqualTo("foo")); } @Test public void existingMessageSourceInParentIsIgnored() { - try (ConfigurableApplicationContext parent = new AnnotationConfigApplicationContext()) { - parent.refresh(); - this.context = new AnnotationConfigApplicationContext(); - this.context.setParent(parent); - TestPropertyValues.of("spring.messages.basename:test/messages") - .applyTo(this.context); - this.context.register(MessageSourceAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class); - this.context.refresh(); - assertThat(this.context.getMessage("foo", null, "Foo message", Locale.UK)) - .isEqualTo("bar"); - } - } - - private void load(String... environment) { - this.context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of(environment).applyTo(this.context); - this.context.register(MessageSourceAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class); - this.context.refresh(); + this.contextRunner.run((parent) -> { + this.contextRunner.withParent(parent) + .withPropertyValues("spring.messages.basename:test/messages") + .run((context) -> assertThat(context.getMessage( + "foo", null, "Foo message", Locale.UK)).isEqualTo("bar")); + }); } @Configuration 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 6f7c6a968a..66fb7540a4 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -117,6 +117,7 @@ content into your application; rather pick only the properties that you need. spring.messages.cache-seconds=-1 # Loaded resource bundle files cache expiration, in seconds. When set to -1, bundles are cached forever. spring.messages.encoding=UTF-8 # Message bundles encoding. spring.messages.fallback-to-system-locale=true # Set whether to fall back to the system Locale if no files for a specific Locale have been found. + spring.messages.use-code-as-default-message=false # Set whether to use the message code as default message instead of throwing a "NoSuchMessageException". Recommended during development only. # OUTPUT spring.output.ansi.enabled=detect # Configure the ANSI output.