Is Spring's @Profile on methods a good practice
Asked Answered
P

3

5

I have a Spring Boot Web application exposing rest services.

I'm asking myself how to correctly manage profiles on Filters. Actually, my app has 2 profiles: dev and prod (you guess what it stands for...)

In prod mode, i have more filters to activate than in dev mode.

My Filters configuration class is the following:

@Configuration
public class FiltersConfig {

    @Bean
    public FilterRegistrationBean filterRegistrationBean(CompositeFilter compositeFilter){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setFilter(compositeFilter);
        return filterRegistrationBean;
    }

    @Bean
    @Profile("dev")
    public CompositeFilter devCompositeFilter(){
        CompositeFilter compositeFilter = new CompositeFilter();
        List<Filter> filtersList = new ArrayList<>();
        //filtersList.add(filter1());
        compositeFilter.setFilters(filtersList);
        return compositeFilter;
    }


    @Bean
    @Profile("prod")
    public CompositeFilter prodCompositeFilter(){
        CompositeFilter compositeFilter = new CompositeFilter();
        List<Filter> filtersList = new ArrayList<>();
        //filtersList.add(filter1());
        compositeFilter.setFilters(filtersList);
        return compositeFilter;
    }
}

My questions are:

  • Is it a good practice to add @Profile on method?
  • Is there a way to force the compiler to exclude classes, methods, etc. annotated with a diferent profiles than the one set as current? (I don't want my production jar/war populated with unnecessary code!)
  • Does spring boot provide a clearer way to organize profiles?

thx.

Plumbiferous answered 12/8, 2016 at 14:26 Comment(0)
A
2

I think it would be better to have configurations for different environments in distinct packages. You don't want to mix your configuration. The structure might look like this:

config
    - Config1.java
    - Config2.java
    dev
        - WebConfig.java
        - DataConfig.java
    prod
        - WebConfig.java
        - DataConfig.java
Antecedency answered 12/8, 2016 at 15:54 Comment(1)
How does this fit in with Spring Boot's ecosystem?Latoyalatoye
I
6

In my own experience, using @Profile in any java code is not a good idea. This is why I think you have to avoid using it in the code:

  1. You can always define property like my.feature-for-the-profile.enabled to achieve the same goal by using profile.
  2. Profiles diverge sometimes, keep every changing configuration as properties give you more control on everything, everywhere.
  3. Spring Boot has a well defined profile-specific externalize properties support (like application-prod.yml). Having profile in you code base will make things more complicated and sometimes misleading.
  4. You can modify or override by using properties more easily than update and recompiling your code.
  5. ProfileCondition (as meta-annotation on @Profile) is not a SpringBootCondition, you can not use /autoconfig to determine is it activated or not.

The bottom line: Define profiles for properties, not for @Configurations nor @Beans.

If you really want to exclude test stuff for your production code, take a look on the documentation of spring-boot-devtools, if your using Maven, you can put all test classes/resources in a separate module, and mark its as <optional>true</optional> or define maven profile for it. Notice, having maven profile and spring boot profile at the same time maybe confusing!

Ianthe answered 22/8, 2017 at 9:15 Comment(1)
My experience also led me to the same conclusion. Defining a property for each feature instead of using @Profile makes the code more readable and gives you more flexibility to mix and match features in the future.Latoyalatoye
A
2

I think it would be better to have configurations for different environments in distinct packages. You don't want to mix your configuration. The structure might look like this:

config
    - Config1.java
    - Config2.java
    dev
        - WebConfig.java
        - DataConfig.java
    prod
        - WebConfig.java
        - DataConfig.java
Antecedency answered 12/8, 2016 at 15:54 Comment(1)
How does this fit in with Spring Boot's ecosystem?Latoyalatoye
C
0

Is it a good practice to add @Profile on method?

It is the spring approach to this problem - so it is in keeping with the spring ecosystem

Is there a way to force the compiler to exclude classes, methods, etc. annotated with a diferent profiles than the one set as current? (I don't want my production jar/war populated with unnecessary code!)

You would have to tune your build to exclude classes - another approach is to configure the beans with id's, and use the ID's and configuration per environment. An approach similar to to

In my experience Profiles are easier

Does spring boot provide a clearer way to organize profiles?

Not that I know of, except the approach in the link above

Circumsolar answered 12/8, 2016 at 14:47 Comment(2)
If i tune my build to exclude class, that means that i have @Profile set on the class and not on the method right? Because if on the same class i have two methods annotated with different profile, i guess both methods will be compiled in the .class file regardless of the profile used at compile time! Tha's exactly what is confusing for me.Plumbiferous
Or use some kind of build process filtering - i guess that would move a profile concept into your build processCircumsolar

© 2022 - 2024 — McMap. All rights reserved.