0

I am upgrading from Spring 4.3 to Spring 5.3 and it seems that placeholders are no longer supported for the @ActiveProviles annotation.

The following code worked with the old Spring version:

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles({"${profileA}","someProfileWithoutPlaceholders"})
@ContextConfiguration(classes = MyApplication.class)
public class MyTest {...}

But it stopped working with the upgrade and now it get

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'nucleus.hibernate.dialect' in value "${nucleus.hibernate.dialect}"
        at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:178)
        at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124)
        at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239)
        at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
        at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175)
        at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:936)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1321)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
        ... 55 more

Note, that 'nucleus.hibernate.dialect' is defined in the application properties referenced by "${profileA}".

As a workaround, I tried to specify the properties as test property source explicitly using

@TestPropertySource(locations={"classpath:/application-${profileA}.properties"}})

and that works.

I am not sure if using placeholders for selecting a Spring profile on a Spring integration test is an officially supported feature. If yes, I consider this a breaking change in the Spring test framework.

Christian
  • 31
  • 3

1 Answers1

0

After debugging around the test case I got a bit more insight on this issue.

It seems that in

org.springframework.core.env.PropertySourcesPropertyResolver#getProperty(java.lang.String, java.lang.Class<T>, boolean)

the test property source 'test' splits up the profiles and has two entries:

spring.profiles.active[0] -> "${profileA}
spring.profiles.active[1] -> "someProfileWithoutPlaceholders"

So when looking up with key "spring.profiles.active", it does not find any value, and org.springframework.core.env.AbstractPropertyResolver#resolveNestedPlaceholders is not called.

This is done in org.springframework.core.env.AbstractEnvironment#doGetActiveProfiles when building the test application context..

In the old Spring version, there was only one map entry:

spring.profiles.active -> "${profileA},someProfileWithoutPlaceholders"

so it found the entry and resolved the placeholder.

Christian
  • 31
  • 3