Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring - Multiple Profiles active

Tags:

java

spring

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"}) public class AppConfigMongodbLinux{...}  @Profile({"Tomcat", "WindowsLocal"}) public class AppConfigMongodbWindowsLocal{...} 

So I'd like that when I use -Dspring.profiles.active=Tomcat,WindowsLocal, it would try to use only the AppConfigMongodbWindowsLocal, but it still tries to register the AppConfigMongodbLinux.

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

Is it possible to make the bean be registerd only when both profiles are active or am I using it incorrectly? :)

Thanks!!


Edit: Posting the full stack.

The error is actually on a property that is missing on the properties, but will this bean get activated? I wanted to understand this to ensure I'm not activating a 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}" 
like image 575
Felipe S. Avatar asked Jun 30 '16 21:06

Felipe S.


People also ask

Can we activate two profiles in Spring boot?

Profiles are a core feature of the framework — allowing us to map our beans to different profiles — for example, dev, test, and prod. We can then activate different profiles in different environments to bootstrap only the beans we need.

How many profile can be defined for a Spring application?

In the application. properties we have set the local profile to be active. With the SpringApplicationBuilder's profiles method we add two additional profiles.

How do I make different profiles in Spring boot?

The solution would be to create more property files and add the "profile" name as the suffix and configure Spring Boot to pick the appropriate properties based on the profile. Then, we need to create three application. properties : application-dev.


1 Answers

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.

like image 91
Laplas Avatar answered Sep 20 '22 12:09

Laplas