2

There are spring boot 2.0.2 configuration

@Configuration
public class ApiConfig {

    @Bean
    @Profile("!tests")
    @ConditionalOnProperty(name = "enabled", havingValue = "true")
    public MyService service() {
        return new MyServiceImpl();
    }

}

... and some controller which should be created and added to application context only if MyService bean is initialized.

@RestController
@ConditionalOnBean(MyService.class)
public class MyController {
   @Autowired
   private MyService service;
}

It works Ok. But occasionally spring boot skips MyController creating. According to the logs MyService is created, but after any other beans(including all controllers), at the end.

Why boot does not process @Configuration beans prior to @RestController? Thanks.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
r.r
  • 245
  • 4
  • 15

1 Answers1

8

Why boot does not process @Configuration beans prior to @Controller? Thanks.

Because Spring doesn't guarantee that.
As well as @ConditionalOnBean warns about this kind of issue in this specification :

The condition can only match the bean definitions that have been processed by the application context so far and, as such, it is strongly recommended to use this condition on auto-configuration classes only. If a candidate bean may be created by another auto-configuration, make sure that the one using this condition runs after.

And you don't use the annotation in an auto-configuration class. You indeed specified it in a class annotated with @RestController.

I think that to achieve your requirement you should move the @RestController bean declaration in a @Configuration class that's imported via an EnableAutoConfiguration entry in spring.factories.

Andy Wilkinson
  • 108,729
  • 24
  • 257
  • 242
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • 1
    unfortunately @dependson annotation does not work for my case. – r.r May 25 '18 at 06:29
  • I tried also @ConditionalOnProperty(name = "enabled", havingValue = "true") on the MyController class. But it always false and never create – r.r May 25 '18 at 06:37
  • Not lucky ! It probably means that `@DependsOn` will not necessarily differ the `@ConditionalOnBean` evaluation. I think that conforming to the doc, using an auto configuration class is probably the way. I don't have much time to make a test right now but it is a very interesting matter. As I would have, I would make a little test. – davidxxx May 25 '18 at 07:37
  • @r.r If you could provide a minimal project that reproduces the issue on a public github or a similarly place, it would be great. – davidxxx May 25 '18 at 08:08
  • unfortunately i cannot share my project. I have found a lot of answers where mentioned that ConditionalOnProperty is right way to disable/enable controllers. But this annotation doesn't not work for controllers marked as RestController. It strange. – r.r May 25 '18 at 12:14
  • @r.r He's not asking you to share your project. Instead, he is asking you to set up a sample project, which is minimal but complete enough to reproduce the issue. – Bhesh Gurung May 25 '18 at 14:56