From 33b60605d778d35ae48d0a177be3862e5d377393 Mon Sep 17 00:00:00 2001 From: Matt Zhang Date: Thu, 7 Mar 2019 23:44:32 +1100 Subject: [PATCH 1/9] BAEL-2569 : EnvironmentPostProcessor in Spring Boot --- .../PriceCalculationApplication.java | 59 +++++++++++++++ ...ceCalculationEnvironmentPostProcessor.java | 71 +++++++++++++++++++ .../PriceCalculationAutoConfig.java | 32 +++++++++ .../calculator/GrossPriceCalculator.java | 23 ++++++ .../calculator/NetPriceCalculator.java | 17 +++++ .../calculator/PriceCalculator.java | 5 ++ .../service/PriceCalculationService.java | 17 +++++ .../main/resources/META-INF/spring.factories | 8 ++- 8 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java new file mode 100644 index 0000000000..01be08d6ae --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java @@ -0,0 +1,59 @@ +package com.baeldung.environmentpostprocessor; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import com.baeldung.environmentpostprocessor.service.PriceCalculationService; + +@SpringBootApplication +public class PriceCalculationApplication implements CommandLineRunner { + + @Autowired + PriceCalculationService priceCalculationService; + + private static final Logger logger = LoggerFactory.getLogger(PriceCalculationApplication.class); + + public static void main(String[] args) { + SpringApplication.run(PriceCalculationApplication.class, args); + } + + @Override + public void run(String... args) throws Exception { + + List params = Arrays.stream(args) + .collect(Collectors.toList()); + if (verifyArguments(params)) { + double singlePrice = Double.valueOf(params.get(0)); + int quantity = Integer.valueOf(params.get(1)); + priceCalculationService.productTotalPrice(singlePrice, quantity); + } else { + logger.error("Invalid arguments " + params.toString()); + } + + } + + private boolean verifyArguments(List args) { + boolean successful = true; + if (args.size() != 2) { + successful = false; + return successful; + } + try { + double singlePrice = Double.valueOf(args.get(0)); + int quantity = Integer.valueOf(args.get(1)); + } catch (NumberFormatException e) { + successful = false; + } + return successful; + + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java new file mode 100644 index 0000000000..1b3099453e --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java @@ -0,0 +1,71 @@ +package com.baeldung.environmentpostprocessor; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.core.Ordered; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.env.StandardEnvironment; + +public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { + + private static final Logger logger = LoggerFactory.getLogger(PriceCalculationEnvironmentPostProcessor.class); + + public static final int DEFAULT_ORDER = Ordered.LOWEST_PRECEDENCE; + private int order = DEFAULT_ORDER; + private static final String PROPERTY_PREFIX = "com.baeldung.environmentpostprocessor."; + private static final String OS_ENV_PROPERTY_CALCUATION_MODE = "calculation_mode"; + private static final String OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE = "gross_calculation_tax_rate"; + private static final String OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE = "NET"; + private static final double OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE = 0; + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + + PropertySource systemEnvironmentPropertySource = environment.getPropertySources() + .get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME); + + Map priceCalculationConfiguration = new LinkedHashMap<>(); + if (isActive(systemEnvironmentPropertySource)) { + priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_CALCUATION_MODE), systemEnvironmentPropertySource.getProperty(OS_ENV_PROPERTY_CALCUATION_MODE)); + priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE), systemEnvironmentPropertySource.getProperty(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE)); + } else { + logger.warn("System environment variables [calculation_mode,gross_calculation_tax_rate] not detected, fallback to default value [calcuation_mode={},gross_calcuation_tax_rate={}]", OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE, + OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); + priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_CALCUATION_MODE), OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE); + priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE), OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); + } + + PropertySource priceCalcuationPropertySource = new MapPropertySource("priceCalcuationPS", priceCalculationConfiguration); + environment.getPropertySources() + .addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, priceCalcuationPropertySource); + + } + + private String key(String key) { + return PROPERTY_PREFIX + key.replaceAll("\\_", "."); + } + + private boolean isActive(PropertySource systemEnvpropertySource) { + if (systemEnvpropertySource.containsProperty(OS_ENV_PROPERTY_CALCUATION_MODE) && systemEnvpropertySource.containsProperty(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE)) { + return true; + } else + return false; + } + + public void setOrder(int order) { + this.order = order; + } + + @Override + public int getOrder() { + return order; + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java new file mode 100644 index 0000000000..c884f043a0 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java @@ -0,0 +1,32 @@ +package com.baeldung.environmentpostprocessor.autoconfig; + +import org.springframework.boot.autoconfigure.AutoConfigureOrder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; + +import com.baeldung.environmentpostprocessor.calculator.GrossPriceCalculator; +import com.baeldung.environmentpostprocessor.calculator.NetPriceCalculator; +import com.baeldung.environmentpostprocessor.calculator.PriceCalculator; + +@Configuration +@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) +public class PriceCalculationAutoConfig { + + @Bean + @ConditionalOnProperty(name = "com.baeldung.environmentpostprocessor.calculation.mode", havingValue = "NET") + @ConditionalOnMissingBean + public PriceCalculator getNetPriceCalculator() { + return new NetPriceCalculator(); + } + + @Bean + @ConditionalOnProperty(name = "com.baeldung.environmentpostprocessor.calculation.mode", havingValue = "GROSS") + @ConditionalOnMissingBean + public PriceCalculator getGrossPriceCalculator() { + return new GrossPriceCalculator(); + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java new file mode 100644 index 0000000000..f8f797bd66 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java @@ -0,0 +1,23 @@ +package com.baeldung.environmentpostprocessor.calculator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; + +public class GrossPriceCalculator implements PriceCalculator { + + private static final Logger logger = LoggerFactory.getLogger(GrossPriceCalculator.class); + + @Value("${com.baeldung.environmentpostprocessor.gross.calculation.tax.rate}") + double taxRate; + + @Override + public double calculate(double singlePrice, int quantity) { + logger.info("Gross based price calculation with input parameters [singlePrice = {},quantity= {} ], {} percent tax applied.", singlePrice, quantity, taxRate * 100); + double netPrice = singlePrice * quantity; + double result = Math.round(netPrice * (1 + taxRate)); + logger.info("Calcuation result is {}", result); + return result; + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java new file mode 100644 index 0000000000..263dff6247 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java @@ -0,0 +1,17 @@ +package com.baeldung.environmentpostprocessor.calculator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NetPriceCalculator implements PriceCalculator { + + private static final Logger logger = LoggerFactory.getLogger(GrossPriceCalculator.class); + + @Override + public double calculate(double singlePrice, int quantity) { + logger.info("Net based price calculation with input parameters [singlePrice = {},quantity= {} ], NO tax applied.", singlePrice, quantity); + double result = Math.round(singlePrice * quantity); + logger.info("Calcuation result is {}", result); + return result; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java new file mode 100644 index 0000000000..9d7bef93a4 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java @@ -0,0 +1,5 @@ +package com.baeldung.environmentpostprocessor.calculator; + +public interface PriceCalculator { + public double calculate(double singlePrice, int quantity); +} diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java new file mode 100644 index 0000000000..0e4eb39506 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java @@ -0,0 +1,17 @@ +package com.baeldung.environmentpostprocessor.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baeldung.environmentpostprocessor.calculator.PriceCalculator; + +@Service +public class PriceCalculationService { + + @Autowired + PriceCalculator priceCalculator; + + public double productTotalPrice(double singlePrice, int quantity) { + return priceCalculator.calculate(singlePrice, quantity); + } +} diff --git a/spring-boot/src/main/resources/META-INF/spring.factories b/spring-boot/src/main/resources/META-INF/spring.factories index e3d3aa4c8e..d8a01bbf82 100644 --- a/spring-boot/src/main/resources/META-INF/spring.factories +++ b/spring-boot/src/main/resources/META-INF/spring.factories @@ -1 +1,7 @@ -org.springframework.boot.diagnostics.FailureAnalyzer=com.baeldung.failureanalyzer.MyBeanNotOfRequiredTypeFailureAnalyzer \ No newline at end of file +org.springframework.boot.diagnostics.FailureAnalyzer=com.baeldung.failureanalyzer.MyBeanNotOfRequiredTypeFailureAnalyzer +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +com.baeldung.environmentpostprocessor.autoconfig.PriceCalculationAutoConfig + +org.springframework.boot.env.EnvironmentPostProcessor=\ +com.baeldung.environmentpostprocessor.PriceCalculationEnvironmentPostProcessor + From bbb98f7a91a91336fb47ae71651400b2b8516bab Mon Sep 17 00:00:00 2001 From: Matt Zhang Date: Mon, 11 Mar 2019 23:49:35 +1100 Subject: [PATCH 2/9] BAEL-2569 add test --- ...ationEnvironmentPostProcessorLiveTest.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java diff --git a/spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java b/spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java new file mode 100644 index 0000000000..352e7941fb --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java @@ -0,0 +1,29 @@ +package com.baeldung.environmentpostprocessor; + +import static org.junit.Assert.assertTrue; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.environmentpostprocessor.service.PriceCalculationService; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = PriceCalculationApplication.class) +public class PriceCalculationEnvironmentPostProcessorLiveTest { + + @Autowired + PriceCalculationService pcService; + + + @Test + public void WhenSetGrossEnvironmentVariable_ThenTaxApplied() { + double total = pcService.productTotalPrice(100, 4); + + Assert.assertEquals(400.0,total); + } + +} From a0227300bf92b3609a554916c8f70aa710d09900 Mon Sep 17 00:00:00 2001 From: "Matt Zhang (EXT)" Date: Wed, 13 Mar 2019 11:56:26 +1100 Subject: [PATCH 3/9] BAEL-2569 update test --- ...CalculationEnvironmentPostProcessorLiveTest.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java b/spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java index 352e7941fb..54af217346 100644 --- a/spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java +++ b/spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java @@ -1,8 +1,7 @@ package com.baeldung.environmentpostprocessor; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -14,16 +13,14 @@ import com.baeldung.environmentpostprocessor.service.PriceCalculationService; @RunWith(SpringRunner.class) @SpringBootTest(classes = PriceCalculationApplication.class) public class PriceCalculationEnvironmentPostProcessorLiveTest { - + @Autowired PriceCalculationService pcService; - - + @Test - public void WhenSetGrossEnvironmentVariable_ThenTaxApplied() { + public void whenSetNetEnvironmentVariablebyDefault_thenNoTaxApplied() { double total = pcService.productTotalPrice(100, 4); - - Assert.assertEquals(400.0,total); + assertEquals(400.0, total, 0); } } From 9f8058a5603ced4177f5bc42ca7b8dbd408a5953 Mon Sep 17 00:00:00 2001 From: Matt Zhang Date: Fri, 29 Mar 2019 23:46:43 +1100 Subject: [PATCH 4/9] BAEL-2569 refactoring the class PriceCalculationEnvironmentPostProcessor --- ...ceCalculationEnvironmentPostProcessor.java | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java index 1b3099453e..42cbd1e90f 100644 --- a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java @@ -8,17 +8,17 @@ import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; import org.springframework.core.env.StandardEnvironment; -public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { +@Order(Ordered.LOWEST_PRECEDENCE) +public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPostProcessor { private static final Logger logger = LoggerFactory.getLogger(PriceCalculationEnvironmentPostProcessor.class); - public static final int DEFAULT_ORDER = Ordered.LOWEST_PRECEDENCE; - private int order = DEFAULT_ORDER; private static final String PROPERTY_PREFIX = "com.baeldung.environmentpostprocessor."; private static final String OS_ENV_PROPERTY_CALCUATION_MODE = "calculation_mode"; private static final String OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE = "gross_calculation_tax_rate"; @@ -28,26 +28,34 @@ public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPost @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { - PropertySource systemEnvironmentPropertySource = environment.getPropertySources() + PropertySource systemEnvPropertySource = environment.getPropertySources() .get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME); - Map priceCalculationConfiguration = new LinkedHashMap<>(); - if (isActive(systemEnvironmentPropertySource)) { - priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_CALCUATION_MODE), systemEnvironmentPropertySource.getProperty(OS_ENV_PROPERTY_CALCUATION_MODE)); - priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE), systemEnvironmentPropertySource.getProperty(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE)); + Map mapPropertySource = new LinkedHashMap<>(); + if (isActive(systemEnvPropertySource)) { + populatePropertySource(systemEnvPropertySource, mapPropertySource); } else { logger.warn("System environment variables [calculation_mode,gross_calculation_tax_rate] not detected, fallback to default value [calcuation_mode={},gross_calcuation_tax_rate={}]", OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE, OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); - priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_CALCUATION_MODE), OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE); - priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE), OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); + populateDefaultPropertySource(mapPropertySource); } - PropertySource priceCalcuationPropertySource = new MapPropertySource("priceCalcuationPS", priceCalculationConfiguration); + PropertySource priceCalcuationPropertySource = new MapPropertySource("priceCalcuationPS", mapPropertySource); environment.getPropertySources() .addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, priceCalcuationPropertySource); } + private void populatePropertySource(PropertySource source, Map target) { + target.put(key(OS_ENV_PROPERTY_CALCUATION_MODE), source.getProperty(OS_ENV_PROPERTY_CALCUATION_MODE)); + target.put(key(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE), source.getProperty(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE)); + } + + private void populateDefaultPropertySource(Map target) { + target.put(key(OS_ENV_PROPERTY_CALCUATION_MODE), OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE); + target.put(key(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE), OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); + } + private String key(String key) { return PROPERTY_PREFIX + key.replaceAll("\\_", "."); } @@ -59,13 +67,4 @@ public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPost return false; } - public void setOrder(int order) { - this.order = order; - } - - @Override - public int getOrder() { - return order; - } - } From 99a3aa5bab5e066bd8470ac2619160aaab19e788 Mon Sep 17 00:00:00 2001 From: Matt Zhang Date: Sun, 31 Mar 2019 22:42:32 +1100 Subject: [PATCH 5/9] BAEL-2569: changes to class PriceCalculationEnvironmentPostProcessor --- ...ceCalculationEnvironmentPostProcessor.java | 69 +++++++++++-------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java index 42cbd1e90f..ca6d6cc28f 100644 --- a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java @@ -1,7 +1,12 @@ package com.baeldung.environmentpostprocessor; +import static org.springframework.core.env.StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME; + +import java.util.Arrays; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,56 +17,62 @@ import org.springframework.core.annotation.Order; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; -import org.springframework.core.env.StandardEnvironment; @Order(Ordered.LOWEST_PRECEDENCE) public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPostProcessor { private static final Logger logger = LoggerFactory.getLogger(PriceCalculationEnvironmentPostProcessor.class); - private static final String PROPERTY_PREFIX = "com.baeldung.environmentpostprocessor."; - private static final String OS_ENV_PROPERTY_CALCUATION_MODE = "calculation_mode"; - private static final String OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE = "gross_calculation_tax_rate"; - private static final String OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE = "NET"; - private static final double OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE = 0; + private static final String PREFIX = "com.baeldung.environmentpostprocessor."; + private static final String CALCUATION_MODE = "calculation_mode"; + private static final String GROSS_CALCULATION_TAX_RATE = "gross_calculation_tax_rate"; + private static final String CALCUATION_MODE_DEFAULT_VALUE = "NET"; + private static final double GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE = 0; + + List names = Arrays.asList(CALCUATION_MODE, GROSS_CALCULATION_TAX_RATE); + + private static Map defaults = new LinkedHashMap<>(); + static { + defaults.put(CALCUATION_MODE, CALCUATION_MODE_DEFAULT_VALUE); + defaults.put(GROSS_CALCULATION_TAX_RATE, GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); + } @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { - PropertySource systemEnvPropertySource = environment.getPropertySources() - .get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME); + PropertySource system = environment.getPropertySources() + .get(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME); - Map mapPropertySource = new LinkedHashMap<>(); - if (isActive(systemEnvPropertySource)) { - populatePropertySource(systemEnvPropertySource, mapPropertySource); - } else { - logger.warn("System environment variables [calculation_mode,gross_calculation_tax_rate] not detected, fallback to default value [calcuation_mode={},gross_calcuation_tax_rate={}]", OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE, - OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); - populateDefaultPropertySource(mapPropertySource); + Map prefixed = new LinkedHashMap<>(); + + if (!hasOurPriceProperties(system)) { + // Baeldung-internal code so this doesn't break other examples + logger.warn("System environment variables [calculation_mode,gross_calculation_tax_rate] not detected, fallback to default value [calcuation_mode={},gross_calcuation_tax_rate={}]", CALCUATION_MODE_DEFAULT_VALUE, + GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); + prefixed = names.stream() + .collect(Collectors.toMap(this::rename, this::getDefaultValue)); + environment.getPropertySources() + .addAfter(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, new MapPropertySource("prefixer", prefixed)); + return; } - PropertySource priceCalcuationPropertySource = new MapPropertySource("priceCalcuationPS", mapPropertySource); + prefixed = names.stream() + .collect(Collectors.toMap(this::rename, system::getProperty)); environment.getPropertySources() - .addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, priceCalcuationPropertySource); + .addAfter(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, new MapPropertySource("prefixer", prefixed)); } - private void populatePropertySource(PropertySource source, Map target) { - target.put(key(OS_ENV_PROPERTY_CALCUATION_MODE), source.getProperty(OS_ENV_PROPERTY_CALCUATION_MODE)); - target.put(key(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE), source.getProperty(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE)); + private Object getDefaultValue(String key) { + return defaults.get(key); } - private void populateDefaultPropertySource(Map target) { - target.put(key(OS_ENV_PROPERTY_CALCUATION_MODE), OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE); - target.put(key(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE), OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); + private String rename(String key) { + return PREFIX + key.replaceAll("\\_", "."); } - private String key(String key) { - return PROPERTY_PREFIX + key.replaceAll("\\_", "."); - } - - private boolean isActive(PropertySource systemEnvpropertySource) { - if (systemEnvpropertySource.containsProperty(OS_ENV_PROPERTY_CALCUATION_MODE) && systemEnvpropertySource.containsProperty(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE)) { + private boolean hasOurPriceProperties(PropertySource system) { + if (system.containsProperty(CALCUATION_MODE) && system.containsProperty(GROSS_CALCULATION_TAX_RATE)) { return true; } else return false; From f5ac80e332dca0488c81bf7ee86fce2114aaa068 Mon Sep 17 00:00:00 2001 From: Matt Zhang Date: Sun, 7 Apr 2019 22:42:15 +1000 Subject: [PATCH 6/9] BAEL-2569 move code to spring-boot-ops module --- .../PriceCalculationApplication.java | 2 +- .../PriceCalculationEnvironmentPostProcessor.java | 0 .../autoconfig/PriceCalculationAutoConfig.java | 0 .../calculator/GrossPriceCalculator.java | 0 .../calculator/NetPriceCalculator.java | 0 .../calculator/PriceCalculator.java | 0 .../service/PriceCalculationService.java | 0 .../src/main/resources/META-INF/spring.factories | 6 ++++++ .../PriceCalculationEnvironmentPostProcessorLiveTest.java | 0 spring-boot/src/main/resources/META-INF/spring.factories | 5 ----- 10 files changed, 7 insertions(+), 6 deletions(-) rename {spring-boot => spring-boot-ops}/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java (96%) rename {spring-boot => spring-boot-ops}/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java (100%) rename {spring-boot => spring-boot-ops}/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java (100%) rename {spring-boot => spring-boot-ops}/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java (100%) rename {spring-boot => spring-boot-ops}/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java (100%) rename {spring-boot => spring-boot-ops}/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java (100%) rename {spring-boot => spring-boot-ops}/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java (100%) create mode 100644 spring-boot-ops/src/main/resources/META-INF/spring.factories rename {spring-boot => spring-boot-ops}/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java (100%) diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java b/spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java similarity index 96% rename from spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java rename to spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java index 01be08d6ae..ed912d8c0a 100644 --- a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java +++ b/spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java @@ -35,7 +35,7 @@ public class PriceCalculationApplication implements CommandLineRunner { int quantity = Integer.valueOf(params.get(1)); priceCalculationService.productTotalPrice(singlePrice, quantity); } else { - logger.error("Invalid arguments " + params.toString()); + logger.warn("Invalid arguments " + params.toString()); } } diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java b/spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java similarity index 100% rename from spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java rename to spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java b/spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java similarity index 100% rename from spring-boot/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java rename to spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java b/spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java similarity index 100% rename from spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java rename to spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java b/spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java similarity index 100% rename from spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java rename to spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java b/spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java similarity index 100% rename from spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java rename to spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java b/spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java similarity index 100% rename from spring-boot/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java rename to spring-boot-ops/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java diff --git a/spring-boot-ops/src/main/resources/META-INF/spring.factories b/spring-boot-ops/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000000..c36b67f8d7 --- /dev/null +++ b/spring-boot-ops/src/main/resources/META-INF/spring.factories @@ -0,0 +1,6 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +com.baeldung.environmentpostprocessor.autoconfig.PriceCalculationAutoConfig + +org.springframework.boot.env.EnvironmentPostProcessor=\ +com.baeldung.environmentpostprocessor.PriceCalculationEnvironmentPostProcessor + diff --git a/spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java b/spring-boot-ops/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java similarity index 100% rename from spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java rename to spring-boot-ops/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java diff --git a/spring-boot/src/main/resources/META-INF/spring.factories b/spring-boot/src/main/resources/META-INF/spring.factories index d8a01bbf82..336477df96 100644 --- a/spring-boot/src/main/resources/META-INF/spring.factories +++ b/spring-boot/src/main/resources/META-INF/spring.factories @@ -1,7 +1,2 @@ org.springframework.boot.diagnostics.FailureAnalyzer=com.baeldung.failureanalyzer.MyBeanNotOfRequiredTypeFailureAnalyzer -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.baeldung.environmentpostprocessor.autoconfig.PriceCalculationAutoConfig - -org.springframework.boot.env.EnvironmentPostProcessor=\ -com.baeldung.environmentpostprocessor.PriceCalculationEnvironmentPostProcessor From 608db42334c844b1b503bde30d9423423ec840b2 Mon Sep 17 00:00:00 2001 From: Matt Zhang Date: Sat, 18 May 2019 19:24:25 +1000 Subject: [PATCH 7/9] BAEL-2878 Guide to Spring's ApplicationContextRunner --- .../service/CustomService.java | 10 +++ .../service/DefaultService.java | 10 +++ .../service/SimpleService.java | 7 ++ .../ConditionalOnBeanTest.java | 77 +++++++++++++++++++ .../ConditionalOnClassTest.java | 76 ++++++++++++++++++ .../ConditionalOnPropertyTest.java | 64 +++++++++++++++ .../ConditionalOnPropertyTest.properties | 1 + 7 files changed, 245 insertions(+) create mode 100644 spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/CustomService.java create mode 100644 spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/DefaultService.java create mode 100644 spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/SimpleService.java create mode 100644 spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanTest.java create mode 100644 spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassTest.java create mode 100644 spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyTest.java create mode 100644 spring-boot-autoconfiguration/src/test/resources/ConditionalOnPropertyTest.properties diff --git a/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/CustomService.java b/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/CustomService.java new file mode 100644 index 0000000000..634e49fed3 --- /dev/null +++ b/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/CustomService.java @@ -0,0 +1,10 @@ +package com.baeldung.autoconfiguration.service; + +public class CustomService implements SimpleService { + + @Override + public String serve() { + return "Custom Service"; + } + +} diff --git a/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/DefaultService.java b/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/DefaultService.java new file mode 100644 index 0000000000..ee91bcb051 --- /dev/null +++ b/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/DefaultService.java @@ -0,0 +1,10 @@ +package com.baeldung.autoconfiguration.service; + +public class DefaultService implements SimpleService { + + @Override + public String serve() { + return "Default Service"; + } + +} diff --git a/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/SimpleService.java b/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/SimpleService.java new file mode 100644 index 0000000000..b6c72d7159 --- /dev/null +++ b/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/SimpleService.java @@ -0,0 +1,7 @@ +package com.baeldung.autoconfiguration.service; + +public interface SimpleService { + + public String serve(); + +} diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanTest.java new file mode 100644 index 0000000000..313d1253c5 --- /dev/null +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanTest.java @@ -0,0 +1,77 @@ +package com.baeldung.autoconfiguration; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +public class ConditionalOnBeanTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + + @Test + public void whenDependentBeanIsPresent_thenConditionalBeanCreated() { + this.contextRunner.withUserConfiguration(basicConfiguration.class, ConditionalOnBeanConfiguration.class) + .run((context) -> { + assertThat(context).hasBean("created"); + assertThat(context).getBean("created") + .isEqualTo("This is always created"); + assertThat(context).hasBean("createOnBean"); + assertThat(context).getBean("createOnBean") + .isEqualTo("This is created when bean (name=created) is present"); + }); + } + + @Test + public void whenDependentBeanIsPresent_thenConditionalMissingBeanIgnored() { + this.contextRunner.withUserConfiguration(basicConfiguration.class, ConditionalOnMissingBeanConfiguration.class) + .run((context) -> { + assertThat(context).hasBean("created"); + assertThat(context).getBean("created") + .isEqualTo("This is always created"); + assertThat(context).doesNotHaveBean("createOnMissingBean"); + }); + } + + @Test + public void whenDependentBeanIsNotPresent_thenConditionalMissingBeanCreated() { + this.contextRunner.withUserConfiguration(ConditionalOnMissingBeanConfiguration.class) + .run((context) -> { + assertThat(context).hasBean("createOnMissingBean"); + assertThat(context).getBean("createOnMissingBean") + .isEqualTo("This is created when bean (name=created) is missing"); + assertThat(context).doesNotHaveBean("created"); + }); + } + + @Configuration + protected static class basicConfiguration { + @Bean + public String created() { + return "This is always created"; + } + } + + @Configuration + @ConditionalOnBean(name = "created") + protected static class ConditionalOnBeanConfiguration { + @Bean + public String createOnBean() { + return "This is created when bean (name=created) is present"; + } + } + + @Configuration + @ConditionalOnMissingBean(name = "created") + protected static class ConditionalOnMissingBeanConfiguration { + @Bean + public String createOnMissingBean() { + return "This is created when bean (name=created) is missing"; + } + } + +} diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassTest.java new file mode 100644 index 0000000000..7f01ea85d4 --- /dev/null +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassTest.java @@ -0,0 +1,76 @@ +package com.baeldung.autoconfiguration; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; +import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +public class ConditionalOnClassTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + + @Test + public void whenDependentClassIsPresent_thenBeanCreated() { + this.contextRunner.withUserConfiguration(ConditionalOnClassConfiguration.class) + .run(context -> { + assertThat(context).hasBean("created"); + assertThat(context.getBean("created")).isEqualTo("This is created when ConditionalOnClassTest is present on the classpath"); + }); + } + + @Test + public void whenDependentClassIsPresent_thenBeanMissing() { + this.contextRunner.withUserConfiguration(ConditionalOnMissingClassConfiguration.class) + .run(context -> { + assertThat(context).doesNotHaveBean("missed"); + }); + } + + @Test + public void whenDependentClassIsNotPresent_thenBeanMissing() { + this.contextRunner.withUserConfiguration(ConditionalOnClassConfiguration.class) + .withClassLoader(new FilteredClassLoader(ConditionalOnClassTest.class)) + .run((context) -> { + assertThat(context).doesNotHaveBean("created"); + assertThat(context).doesNotHaveBean(ConditionalOnClassTest.class); + + }); + } + + @Test + public void whenDependentClassIsNotPresent_thenBeanCreated() { + this.contextRunner.withUserConfiguration(ConditionalOnMissingClassConfiguration.class) + .withClassLoader(new FilteredClassLoader(ConditionalOnClassTest.class)) + .run((context) -> { + assertThat(context).hasBean("missed"); + assertThat(context).getBean("missed") + .isEqualTo("This is missed when ConditionalOnClassTest is present on the classpath"); + assertThat(context).doesNotHaveBean(ConditionalOnClassTest.class); + + }); + } + + @Configuration + @ConditionalOnClass(ConditionalOnClassTest.class) + protected static class ConditionalOnClassConfiguration { + @Bean + public String created() { + return "This is created when ConditionalOnClassTest is present on the classpath"; + } + } + + @Configuration + @ConditionalOnMissingClass("com.baeldung.autoconfiguration.ConditionalOnClassTest") + protected static class ConditionalOnMissingClassConfiguration { + @Bean + public String missed() { + return "This is missed when ConditionalOnClassTest is present on the classpath"; + } + } + +} diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyTest.java new file mode 100644 index 0000000000..2c09b72dda --- /dev/null +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyTest.java @@ -0,0 +1,64 @@ +package com.baeldung.autoconfiguration; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.TestPropertySource; + +import com.baeldung.autoconfiguration.service.CustomService; +import com.baeldung.autoconfiguration.service.DefaultService; +import com.baeldung.autoconfiguration.service.SimpleService; + +public class ConditionalOnPropertyTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + + @Test + public void whenGivenCustomPropertyValue_thenCustomServiceCreated() { + this.contextRunner.withPropertyValues("com.baeldung.service=custom") + .withUserConfiguration(SimpleServiceConfiguration.class) + .run(context -> { + assertThat(context).hasBean("customService"); + SimpleService simpleService = context.getBean(CustomService.class); + assertThat(simpleService.serve()).isEqualTo("Custom Service"); + assertThat(context).doesNotHaveBean("defaultService"); + }); + } + + @Test + public void whenGivenDefaultPropertyValue_thenDefaultServiceCreated() { + this.contextRunner.withPropertyValues("com.baeldung.service=default") + .withUserConfiguration(SimpleServiceConfiguration.class) + .run(context -> { + assertThat(context).hasBean("defaultService"); + SimpleService simpleService = context.getBean(DefaultService.class); + assertThat(simpleService.serve()).isEqualTo("Default Service"); + assertThat(context).doesNotHaveBean("customService"); + }); + } + + @Configuration + @TestPropertySource("classpath:ConditionalOnPropertyTest.properties") + protected static class SimpleServiceConfiguration { + + @Bean + @ConditionalOnProperty(name = "com.baeldung.service", havingValue = "default") + @ConditionalOnMissingBean + public DefaultService defaultService() { + return new DefaultService(); + } + + @Bean + @ConditionalOnProperty(name = "com.baeldung.service", havingValue = "custom") + @ConditionalOnMissingBean + public CustomService customService() { + return new CustomService(); + } + } + +} diff --git a/spring-boot-autoconfiguration/src/test/resources/ConditionalOnPropertyTest.properties b/spring-boot-autoconfiguration/src/test/resources/ConditionalOnPropertyTest.properties new file mode 100644 index 0000000000..b6334bc1ce --- /dev/null +++ b/spring-boot-autoconfiguration/src/test/resources/ConditionalOnPropertyTest.properties @@ -0,0 +1 @@ +com.baeldung.service=custom \ No newline at end of file From 6754e4cd218f2ba032ef798e48c9a26410a159a7 Mon Sep 17 00:00:00 2001 From: Matt Zhang Date: Mon, 20 May 2019 21:37:55 +1000 Subject: [PATCH 8/9] BAEL-2878 rename the test --- ... => ConditionalOnBeanIntegrationTest.java} | 2 +- ...=> ConditionalOnClassIntegrationTest.java} | 22 +++++++++---------- ...ConditionalOnPropertyIntegrationTest.java} | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) rename spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/{ConditionalOnBeanTest.java => ConditionalOnBeanIntegrationTest.java} (98%) rename spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/{ConditionalOnClassTest.java => ConditionalOnClassIntegrationTest.java} (80%) rename spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/{ConditionalOnPropertyTest.java => ConditionalOnPropertyIntegrationTest.java} (98%) diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanIntegrationTest.java similarity index 98% rename from spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanTest.java rename to spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanIntegrationTest.java index 313d1253c5..c94b432b9d 100644 --- a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanTest.java +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanIntegrationTest.java @@ -9,7 +9,7 @@ import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -public class ConditionalOnBeanTest { +public class ConditionalOnBeanIntegrationTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassIntegrationTest.java similarity index 80% rename from spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassTest.java rename to spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassIntegrationTest.java index 7f01ea85d4..f2866867f2 100644 --- a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassTest.java +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassIntegrationTest.java @@ -10,7 +10,7 @@ import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -public class ConditionalOnClassTest { +public class ConditionalOnClassIntegrationTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); @@ -19,7 +19,7 @@ public class ConditionalOnClassTest { this.contextRunner.withUserConfiguration(ConditionalOnClassConfiguration.class) .run(context -> { assertThat(context).hasBean("created"); - assertThat(context.getBean("created")).isEqualTo("This is created when ConditionalOnClassTest is present on the classpath"); + assertThat(context.getBean("created")).isEqualTo("This is created when ConditionalOnClassIntegrationTest is present on the classpath"); }); } @@ -34,10 +34,10 @@ public class ConditionalOnClassTest { @Test public void whenDependentClassIsNotPresent_thenBeanMissing() { this.contextRunner.withUserConfiguration(ConditionalOnClassConfiguration.class) - .withClassLoader(new FilteredClassLoader(ConditionalOnClassTest.class)) + .withClassLoader(new FilteredClassLoader(ConditionalOnClassIntegrationTest.class)) .run((context) -> { assertThat(context).doesNotHaveBean("created"); - assertThat(context).doesNotHaveBean(ConditionalOnClassTest.class); + assertThat(context).doesNotHaveBean(ConditionalOnClassIntegrationTest.class); }); } @@ -45,31 +45,31 @@ public class ConditionalOnClassTest { @Test public void whenDependentClassIsNotPresent_thenBeanCreated() { this.contextRunner.withUserConfiguration(ConditionalOnMissingClassConfiguration.class) - .withClassLoader(new FilteredClassLoader(ConditionalOnClassTest.class)) + .withClassLoader(new FilteredClassLoader(ConditionalOnClassIntegrationTest.class)) .run((context) -> { assertThat(context).hasBean("missed"); assertThat(context).getBean("missed") - .isEqualTo("This is missed when ConditionalOnClassTest is present on the classpath"); - assertThat(context).doesNotHaveBean(ConditionalOnClassTest.class); + .isEqualTo("This is missed when ConditionalOnClassIntegrationTest is present on the classpath"); + assertThat(context).doesNotHaveBean(ConditionalOnClassIntegrationTest.class); }); } @Configuration - @ConditionalOnClass(ConditionalOnClassTest.class) + @ConditionalOnClass(ConditionalOnClassIntegrationTest.class) protected static class ConditionalOnClassConfiguration { @Bean public String created() { - return "This is created when ConditionalOnClassTest is present on the classpath"; + return "This is created when ConditionalOnClassIntegrationTest is present on the classpath"; } } @Configuration - @ConditionalOnMissingClass("com.baeldung.autoconfiguration.ConditionalOnClassTest") + @ConditionalOnMissingClass("com.baeldung.autoconfiguration.ConditionalOnClassIntegrationTest") protected static class ConditionalOnMissingClassConfiguration { @Bean public String missed() { - return "This is missed when ConditionalOnClassTest is present on the classpath"; + return "This is missed when ConditionalOnClassIntegrationTest is present on the classpath"; } } diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyIntegrationTest.java similarity index 98% rename from spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyTest.java rename to spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyIntegrationTest.java index 2c09b72dda..c0733722dc 100644 --- a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyTest.java +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyIntegrationTest.java @@ -14,7 +14,7 @@ import com.baeldung.autoconfiguration.service.CustomService; import com.baeldung.autoconfiguration.service.DefaultService; import com.baeldung.autoconfiguration.service.SimpleService; -public class ConditionalOnPropertyTest { +public class ConditionalOnPropertyIntegrationTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); From 066cf2d6f2d9122a648ce016aa31412cd22bd4c2 Mon Sep 17 00:00:00 2001 From: Matt Zhang Date: Sun, 26 May 2019 22:14:10 +1000 Subject: [PATCH 9/9] BAEL-2878 Guide to Spring's ApplicationContextRunner --- .../autoconfiguration/ConditionalOnBeanIntegrationTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanIntegrationTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanIntegrationTest.java index c94b432b9d..32f63edde4 100644 --- a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanIntegrationTest.java +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanIntegrationTest.java @@ -15,7 +15,7 @@ public class ConditionalOnBeanIntegrationTest { @Test public void whenDependentBeanIsPresent_thenConditionalBeanCreated() { - this.contextRunner.withUserConfiguration(basicConfiguration.class, ConditionalOnBeanConfiguration.class) + this.contextRunner.withUserConfiguration(BasicConfiguration.class, ConditionalOnBeanConfiguration.class) .run((context) -> { assertThat(context).hasBean("created"); assertThat(context).getBean("created") @@ -28,7 +28,7 @@ public class ConditionalOnBeanIntegrationTest { @Test public void whenDependentBeanIsPresent_thenConditionalMissingBeanIgnored() { - this.contextRunner.withUserConfiguration(basicConfiguration.class, ConditionalOnMissingBeanConfiguration.class) + this.contextRunner.withUserConfiguration(BasicConfiguration.class, ConditionalOnMissingBeanConfiguration.class) .run((context) -> { assertThat(context).hasBean("created"); assertThat(context).getBean("created") @@ -49,7 +49,7 @@ public class ConditionalOnBeanIntegrationTest { } @Configuration - protected static class basicConfiguration { + protected static class BasicConfiguration { @Bean public String created() { return "This is always created";