Spring - multiple profiles active

I basically have a bean in Spring that I wanted to activate only when 2 profiles are active. Basically, it would be like this:

@Profile({"Tomcat", "Linux"}) public class AppConfigMongodbLinux{...} @Profile({"Tomcat", "WindowsLocal"}) public class AppConfigMongodbWindowsLocal{...} 

Therefore, I would like to use only AppConfigMongodbWindowsLocal when using -Dspring.profiles.active=Tomcat,WindowsLocal , but it is still trying to register AppConfigMongodbLinux .

 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appConfigMongodbLinux': Injection of autowired dependencies failed 

Is it possible to register a bean only if both profiles are active or am I using it incorrectly? :)

Thanks!!


Edit: sending a full stack.

The error is actually in a property that is missing from the properties, but is this a bean activated? I wanted to figure this out to make sure that I am not activating the wrong bean ..

 org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]] ... Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appConfigMongodbLinux': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.Integer mycompany.config.AppConfigMongodbLinux.mongoPort; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'mongo.port' in string value "${mongo.port}" ... 40 more Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.Integer mycompany.config.AppConfigMongodbLinux.mongoPort; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'mongo.port' in string value "${mongo.port}" ... Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'mongo.port' in string value "${mongo.port}" 
+9
source share
3 answers

Unfortunately, @Profile activated if any registered profile is active. There are several ways around this.

  • Apply the general annotation @Profile("Tomcat") to the top-level configuration class, and then apply @Profile("Windows") to the nested configuration class (or @Bean ).
  • If Spring Boot is acceptable as a dependency, use @AllNestedConditions to create an annotation in which AND instead of OR.

It seems that what you are trying to do would be pure writing if you were to use the w060> Boot autoconfiguration boot classes; if it is practical to enter autoconfiguration at this stage of the application life cycle, I recommend considering it.

+6
source

Spring version 5.1 and above offers additional functionality for specifying more complex string profile expressions. In your case, the desired functionality can be achieved as follows:

 @Profile({"Tomcat & Linux"}) @Configuration public class AppConfigMongodbLinux {...} 

Please read the Using @Profile section of the Spring reference documentation for more information.

Update (method level profile expressions): Actually, I tested some @Bean method level profile expressions and everything works like a miracle:

 /** * 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 version 5.1.2 has been tested.

+1
source

All Articles