21

My problem is that I have application, which uses Spring profiles. Building application on server means that the profile is set to "wo-data-init". For other build there is "test" profile. When any of them is activated they are not supposed to run the Bean method, so I though this annotation should work:

@Profile({"!test","!wo-data-init"})

It seems more like it's running if(!test OR !wo-data-init) and in my case I need it to run if(!test AND !wo-data-init) - is it even possible?

kryger
  • 12,906
  • 8
  • 44
  • 65
vul6
  • 441
  • 4
  • 14

3 Answers3

31

In Spring 5.1.4 (Spring Boot 2.1.2) and above it is as easy as:

@Component
@Profile("!a & !b")
public class MyComponent {}

Ref: How to conditionally declare Bean when multiple profiles are not active?

icyerasor
  • 4,973
  • 1
  • 43
  • 52
Jenson
  • 635
  • 2
  • 11
  • 20
12

Spring 4 has brought some cool features for conditional bean creation. In your case, indeed plain @Profile annotation is not enough because it uses OR operator.

One of the solutions you can do is to create your custom annotation and custom condition for it. For example

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional(NoProfilesEnabledCondition.class)
public @interface NoProfilesEnabled {
    String[] value();
}
public class NoProfilesEnabledCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        boolean matches = true;

        if (context.getEnvironment() != null) {
            MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(NoProfileEnabled.class.getName());
            if (attrs != null) {
                for (Object value : attrs.get("value")) {
                    String[] requiredProfiles = (String[]) value;

                    for (String profile : requiredProfiles) {
                        if (context.getEnvironment().acceptsProfiles(profile)) {
                            matches = false;
                        }
                    }

                }
            }
        }
        return matches;
    }
}

Above is quick and dirty modification of ProfileCondition.

Now you can annotate your beans in the way:

@Component
@NoProfilesEnabled({"foo", "bar"})
class ProjectRepositoryImpl implements ProjectRepository { ... }
Maciej Walkowiak
  • 12,372
  • 59
  • 63
-3

I found a better solution

@Profile("default")

Profile default means no foo and no bar profiles.

eballo
  • 769
  • 1
  • 11
  • 20
  • Related to my answer : https://stackoverflow.com/questions/10041410/default-profile-in-spring-3-1 – eballo May 18 '19 at 14:47