kellyfj
kellyfj

Reputation: 6943

In Spring what is the difference between @Profile and @ActiveProfiles

What is the difference between using @Profile and @ActiveProfiles on a Spring Test configuration

@Configuration
@EnableRetry
@ActiveProfiles("unittest") 
static class ContextConfiguration {

and

@Configuration
@EnableRetry
@Profile("unittest") 
static class ContextConfiguration {

Upvotes: 54

Views: 32757

Answers (6)

cse
cse

Reputation: 4104

In short, @Profile defines a profile like a Debug profile and a Production profile etc... However @ActiveProfiles comes into picture in case of an ApplicationContext and defines which profiles should be active if respective ApplicationContext is being used.

As mentioned in JavaDoc of Spring official website:

@Profile

A profile is a named logical grouping that may be activated programmatically via ConfigurableEnvironment.setActiveProfiles(java.lang.String...) or declaratively by setting the spring.profiles.active property as a JVM system property, as an environment variable, or as a Servlet context parameter in web.xml for web applications. Profiles may also be activated declaratively in integration tests via the @ActiveProfiles annotation.

@ActiveProfiles

ActiveProfiles is a class-level annotation that is used to declare which active bean definition profiles should be used when loading an ApplicationContext for test classes.

Also, you can see here for more information about @Profile

Upvotes: 21

user1024314
user1024314

Reputation:

@Profile is used when declaring a bean or configuration. @Profile declares which profile the bean or configuration belongs to.

@ActiveProfiles is used only from tests that are consuming a bean or configuration to enable one or more profiles.

When @ActiveProfiles is specified, it causes the Spring Context to check whether a bean or configuration is annotated with @Profile. If so, that bean or configuration is only loaded if the profile in @ActiveProfiles matches the profile rule in the bean's @Profile annotation.

Upvotes: 2

Samuel Negri
Samuel Negri

Reputation: 519

@Profile is used to define different @Bean definitions for different contexts, e.g:

public class BeanConfiguration {
    @Bean
    @Profile({"local", "dev", "ci-dev", "homolog"})
    public SomeHttpClientBean adyenClientFactorySandbox() {
        return SomeHttpClientBean.builder()
            .url("https://test.example.com")
            .build();
    }

    @Bean
    @Profile("prod")
    public SomeHttpClientBean adyenClientFactorySandbox() {
        return SomeHttpClientBean.builder()
            .url("https://production.example.com")
            .build();
    }
}

Once you have that configuration, when starting your application, all you need to do is set which profile is active, either by spring.profiles.active property or by annotating a class:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@ActiveProfiles("ci-dev")
public class SpringBootTestBase {
    @Test
    ...
}

Upvotes: 3

Navpreet Singh
Navpreet Singh

Reputation: 341

Spring Profiles provide a way to segregate parts of your application configuration.

Any @Component or @Configuration can be marked with @Profile to limit when it is loaded which means that component or configuration will be loaded in the application context only when the active profiles is same as the profile mapped to a component.

To mark a profile active, spring.profiles.active property must be set in application.properties or given as an VM argument as -Dspring.profiles.active=dev

While writing Junit, you would want to activate some profile so as to load the required configuration or Component. Same can be achieved by using @ActiveProfile annotation.

Consider a configuration class which is mapped to profile dev

@Configuration
@Profile("dev")
public class DataSourceConfig {
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost/test");
        ds.setUsername("root");
        ds.setPassword("mnrpass");
        return ds;
    }

    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource());
    }
}

Consider a configuration class which is mapped to profile prod

@Configuration
@Profile("prod")
public class DataSourceConfig {
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:oracle://xxx.xxx.xx.xxx/prod");
        ds.setUsername("dbuser");
        ds.setPassword("prodPass123");
        return ds;
    }

    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource());
    }
}

So, if you want to run your junit test cases in dev profile then you have to use the @ActiveProfile('dev') annotation. This will load the DataSourceConfig bean defined in dev profile.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@ActiveProfiles("dev")
public class Tests{

    // Junit Test cases will use the 'dev' profile DataSource Configuration

}

Conclusion

@Profile is used to map a class to a profile

@ActiveProfile is used to activate a particular profile(s) during junit test class execution

Upvotes: 33

Andrey Dorohovich
Andrey Dorohovich

Reputation: 343

  • with @Profile annotation you set condition to your bean definition, which impacts create or not create this bean in your spring context depending on current active profiles. Example from JavaDoc:

    @Profile({"p1", "!p2"} - registration will occur if profile 'p1' is active or if profile 'p2' is not active.

  • with @ActiveProfiles you set current active profiles. Example:

    @ActiveProfiles({"p2","p3"}) bean with annotation @Profile({"p1", "!p2"} will not be created.

    @ActiveProfiles({"p3"}) bean with annotation @Profile({"p1", "!p2"} will be created.

    @ActiveProfiles({"p1"}) bean with annotation @Profile({"p1", "!p2"} will be created.

Upvotes: 2

Mahozad
Mahozad

Reputation: 24532

Any @Component or @Configuration can be marked with @Profile to limit when it is loaded.

You define @Profile for your:

  1. classes -directly or indirectly- annotated with @Component, including @Configuration classes
  2. methods annotated with @Bean

Then while testing, you choose which profile(s) you want by specifying them in @ActiveProfiles.

ActiveProfiles is a class-level annotation that is used to declare which active bean definition profiles should be used when loading an ApplicationContext for test classes.

It has no effect if used outside of the test context.

Summary

You assign profile to your components with @Profile; while testing select them with @ActiveProfiles, while developing select them with spring.profiles.active property.

Upvotes: 7

Related Questions