I basically have a bean in Spring that I wanted to activate only when 2 profiles are active. Basically, it would be like:
@Profile({\"Tomcat\", \"Linux\"})
p
The first profile is on the Top level. The second I checked like this:
@Autowired
private Environment env;
...
final boolean isMyProfile = Arrays.stream(env.getActiveProfiles()).anyMatch("MyProfile"::equals);
Unfortunately, @Profile
activates if any listed profile is active. There are a couple of ways around this.
@Profile("Tomcat")
annotation to a top-level configuration class, and then apply @Profile("Windows")
to a nested configuration class (or @Bean
method).It looks like what you're trying to do would be clean to write if you were using Spring Boot autoconfiguration classes; if it's practical to introduce autoconfiguration at this stage of your application's lifecycle, I recommend considering it.
@ConditionalOnExpression("#{environment.acceptsProfiles('Tomcat') && environment.acceptsProfiles('Linux')}")
Credits: Spring Source Code. Look up the @ConditionalOnExpression with your IDE then 'find usages' to see relevant examples within the source code. This will enable you to become a better developer.
Spring version 5.1 and above offers additional functionality for specifying more complex profile string expressions. In your case desired functionality can be achieved in the following way:
@Profile({"Tomcat & Linux"})
@Configuration
public class AppConfigMongodbLinux {...}
Please read Using @Profile chapter from Spring reference documentation for more info.
Update (method level profile expressions): Actually I've tested some @Bean method level profile expressions and everything works like a charm:
/**
* Shows basic usage of {@link Profile} annotations applied on method level.
*/
@Configuration
public class MethodLevelProfileConfiguration {
/**
* Point in time related to application startup.
*/
@Profile("qa")
@Bean
public Instant startupInstant() {
return Instant.now();
}
/**
* Point in time related to scheduled shutdown of the application.
*/
@Bean
public Instant shutdownInstant() {
return Instant.MAX;
}
/**
* Point in time of 1970 year.
*/
@Profile("develop & production")
@Bean
public Instant epochInstant() {
return Instant.EPOCH;
}
}
Integration tests:
/**
* Verifies {@link Profile} annotation functionality applied on method-level.
*/
public class MethodLevelProfileConfigurationTest {
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MethodLevelProfileConfiguration.class)
@ActiveProfiles(profiles = "qa")
public static class QaActiveProfileTest {
@Autowired
private ApplicationContext context;
@Test
public void shouldRegisterStartupAndShutdownInstants() {
context.getBean("startupInstant", Instant.class);
context.getBean("shutdownInstant", Instant.class);
try {
context.getBean("epochInstant", Instant.class);
fail();
} catch (NoSuchBeanDefinitionException ex) {
// Legal to ignore.
}
}
}
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MethodLevelProfileConfiguration.class)
@ActiveProfiles(profiles = {"develop", "production"})
public static class MethodProfileExpressionTest {
@Autowired
private ApplicationContext context;
@Test
public void shouldRegisterShutdownAndEpochInstants() {
context.getBean("epochInstant", Instant.class);
context.getBean("shutdownInstant", Instant.class);
try {
context.getBean("startupInstant", Instant.class);
fail();
} catch (NoSuchBeanDefinitionException ex) {
// Legal to ignore.
}
}
}
}
Spring 5.1.2 version was tested.