boredDev
boredDev

Reputation: 336

Adding @Conditional to an existing spring annotation in spring boot


I have an application which uses an existing spring annotation (@EnableResourceServer). I want this particular annotation to be enabled only when a particular property value is not false. To do this, I created a meta-annotation and applied @ConditionalOnProperty on that :

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ConditionalOnProperty(prefix = "custom.resource", name = "enabled", matchIfMissing = true)
@EnableResourceServer
public @interface EnableCustomResourceSecurity {
}

In my application I'm now using @EnableCustomResourceSecurity like :

@EnableCustomResourceSecurity
@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
    SpringApplication.run(MyApplication.class, args);
    }

}

and it all works fine if the property is missing or true but when I change the property to custom.resource.enabled=false I get the following exception :

org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.

I tried putting this annotation in a couple of other places and noticed that when the conditional expression fails for this annotation, any annotation after this also stops getting processed.

What would be the correct way to achieve what I'm trying to do?

Upvotes: 2

Views: 6897

Answers (2)

Mohit Singh
Mohit Singh

Reputation: 524

I would recommend, you don't even need a custom annotation but just an empty configuration as mentioned by Michiel. This configuration, in turn, will also import the @EnableResourceServer annotation.

@Configuration
@EnableResourceServer
@ConditionalOnProperty(prefix = "custom.resource", name = "enabled", matchIfMissing = true)
public class ResourceServerConfig {
    public ResourceServerConfig() {
        System.out.println("initializing ResourceServerConfig ...");
    }
}

If you want to control based on annotation, you can import the same configuration in the custom annotation as below:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ResourceServerConfig.class)
public @interface EnableCustomResourceSecurity {
}

Upvotes: 0

Michiel
Michiel

Reputation: 3410

Your annotation @EnableCustomResourceSecurity has the meta annotation @ConditionalOnProperty. While it may seem as if it enables/disables the @EnableResourceServer annotation, it actually enables/disables your MyApplication bean as a whole. It is as if you would write:

@SpringBootApplication
@ConditionalOnProperty(...)
@EnableResourceServer
public class MyApplication {

To avoid this, simply create an empty SomeConfiguration class and annotate it with your custom annotation:

@Configuration
@EnableCustomResourceSecurity
public class SomeConfiguration {}

Instead of adding it to your MyApplication class.

Upvotes: 5

Related Questions