I have a Spring Boot 2.7.14 application packaged as follows:
com.abc.globalpayments.feeds.downstream.dailycashreport
com.abc.globalpayments.feeds.downstream.dailycashreport.acquire
com.abc.globalpayments.feeds.downstream.dailycashreport.acquire.random
com.abc.globalpayments.feeds.downstream.dailycashreport.distribute
com.abc.globalpayments.feeds.downstream.dailycashreport.domain
com.abc.globalpayments.feeds.downstream.dailycashreport.generate
com.abc.globalpayments.feeds.downstream.dailycashreport.process
The root *.dailycashreport
package contains the entry point:
@Slf4j
@SpringBootApplication
@PropertySource(value = "classpath:feeds-config.yml", factory = com.abc.globalpayments.feeds.downstream.YamlPropertySourceFactory.class)
public class DcrDataFactoryApplication implements CommandLineRunner {
@Autowired
private SyntheticRunner runner; data sources
public static void main(String[] args) {//}
YamlPropertySourceFactory seen above is as follows:
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) throws IOException {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(encodedResource.getResource());
Properties properties = factory.getObject();
return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
}
}
There are the following 3 resources under src/main/resources
:
application.yml:
spring:
application:
name: daily-cash-report-application
sftp:
host: dev
port: 22
user: dev
stagingDir: /opt/ccc/Data/Stage
tmpDir: /opt/ccc/abcd/tmp
#privateKey:
privateKey: file:///C:/Users/12345/AppData/Roaming/SSH/UserKeys/distributessh
chmod: 664
file:
stagingDir: /opt/ccc/Data/Stage
tmpDir: C:\tmp
feeds-config.yml
feeds:
downstream:
another-system:
output-file-name: other.txt
daily-cash-report:
output-file-name: dcr.txt
test:
records-to-generate:
pc: 10
dp: 5
z: 1
and logback.xml
In tests, I'm using the following setup:
@SpringBootTest
class DataMarshallerServiceTest {
@Autowired
private DataMarshallerService cut;
@Autowired
//
The above setup builds and works fine, however as soon as I'm trying to introduce a dev
profile by renaming application.yml
into application-dev.yml
, I start encountering the following exception as part of the build in tests execution:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'sftp.host' in value "${sftp.host}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:180)
Here's the launch profile in my STS IDE:
However, the error manifests during the build time, when executing
mvn clear package -P dcr
which is equivalent to the following STS Maven config also present in STS:
What is it I'm missing so that Spring profiles start functioning properly?
Could it be that since the *App
has YamlPropertySourceFactory
configured, the rest of the properties need to be specified explicitly?
Thank you in advance.
I've made the following assumption and an attempt to validate it, it seems to work, so I'll leave it here as a potential answer to be, potentially, challenged.
Apparently tests need to be pointed at the proper profile which is not part of the @SpringBootTest
annotation itself.
Either one of the following 3 configurations seem to make the build work:
Option 1:
I've updated all the failing test cases with the following annotation after the @SpringBootTest
:
@ActiveProfiles(profiles = "dev")
while adding the following stanza inside the application.yml
:
spring:
application:
name: daily-cash-report-application
profiles: dev
It also works without the above stanza if I rename application.yml
into application-dev.yml
.
Option 2:
Another, even simpler approach is as follows:
@ActiveProfiles(profiles = "dev")
as above whilemvn clean package -P dcr -Dspring.profiles.active=dev
and
application-dev.yml
out of src/main/resources/Option 3
No need to either:
application-dev.yml
file@ActiveProfiles(profiles = "dev")
annotation-Dspring.profiles.active=dev
,-Dspring.profiles.active=dev
as a parameter to MavenSimply:
Drop a copy of application.yml
into src/test/resources/ folder so as to be picked up and used for tests execution via mvn clean package -P dcr
I'll let someone more authoritative to confirm that these are the right approaches and to validate that this test behavior in Spring is by design.
Thank you for reading.