Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make @ConditionalOnBean with multiple beans an AND rather than an OR #5279

Closed
wilkinsona opened this issue Feb 29, 2016 · 10 comments
Closed

Make @ConditionalOnBean with multiple beans an AND rather than an OR #5279

wilkinsona opened this issue Feb 29, 2016 · 10 comments
Assignees
Milestone

Comments

@wilkinsona
Copy link
Member

@wilkinsona wilkinsona commented Feb 29, 2016

No description provided.

@philwebb
Copy link
Member

@philwebb philwebb commented Feb 29, 2016

Probably a 2.0 change and one that I'm not too keen on since it could break code in a very subtle way.

@wilkinsona
Copy link
Member Author

@wilkinsona wilkinsona commented Feb 29, 2016

I thought you'd say that :)

@derTobsch
Copy link

@derTobsch derTobsch commented Jan 27, 2017

I would be nice if we get a AND with 2.0. :-) I have the case that I want to expose a bean, when two other beans are on the bean factory. Now I got a workaround with one @ConditionalOnBean annotation on the method and one at class level.

Could it be an idea to provide an annotation attribute to switch between "or" and "and" and the default would still be "or" so nothing would break?

@philwebb
Copy link
Member

@philwebb philwebb commented Jan 27, 2017

@derTobsch Have you seen the AllNestedConditions, AnyNestedCondition and NoneNestedConditions classes? You can use those to combine conditions together.

@derTobsch
Copy link

@derTobsch derTobsch commented Jan 28, 2017

@philwebb that's a good reminder. I knew them but barely use them. I give them a try, that should work just fine. thanks

@derTobsch
Copy link

@derTobsch derTobsch commented Jan 28, 2017

I tried it and it does work but it feels a little bit cumbersome :-)

Here the code for other users finding this issue. I want that both beans are already in the bean factory before running this auto configuration. So i created a inner class and added @Conditional(ConditionOnSecurityAndDiscovery.class) on my auto configuration class.

    static class ConditionOnSecurityAndDiscovery extends AllNestedConditions {

        ConditionOnSecurityAndDiscovery() {

            super(ConfigurationPhase.REGISTER_BEAN);
        }

        @ConditionalOnBean(CoffeeNetAppService.class)
        static class OnDiscovery {
        }

        @ConditionalOnBean(CoffeeNetCurrentUserService.class)
        static class OnSecurity {
        }
    }

examples here e.g. https://github.com/spring-projects/spring-boot/blob/8470ecb4d05c2bcaadd9c58cc7564d7687ae02cd/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastJpaDependencyAutoConfiguration.java

I must say, that I would prefer something like this below in in the 2.0 version

@ConditionalOnBean(classes = {CoffeeNetAppService.class, CoffeeNetCurrentUserService.class}, operation = Operation.AND)

Thanks for your help @philwebb

@philwebb philwebb added this to the 2.0.0.M1 milestone Feb 2, 2017
@wilkinsona wilkinsona changed the title Consider making @ConditionalOnBean with multiple beans an AND rather than an OR Make @ConditionalOnBean with multiple beans an AND rather than an OR Feb 2, 2017
@wilkinsona wilkinsona self-assigned this Feb 3, 2017
@wilkinsona wilkinsona closed this in 457d041 Feb 6, 2017
@alwaysastudent
Copy link

@alwaysastudent alwaysastudent commented Mar 6, 2017

I have been relying on the OR functionality of ConditionalOnBean. Is it possible that original feature be made possible within the ConditionalOnBean annotation itself @derTobsch has been suggesting.

@ConditionalOnBean(classes = {Bean1.class, Bean2.class}, operation = Operation.OR)

Resorting to write AnyNestedCondition for each of the original OR functions would be cumbersome indeed.

@wilkinsona
Copy link
Member Author

@wilkinsona wilkinsona commented Mar 6, 2017

We discussed the possibility of adding an attribute and decided that it exposed complexity to everyone that was only of use in edge cases so we decided against doing so. Sorry, but we're not going to change that unless a compelling use case that isn't an edge case is brought to our attention.

If you're comfortable with writing the more sophisticated injection logic required by an OR (using an ObjectProvider or @Autowired(required=false), for example) then you'll also need to use AnyNestedCondition.

@heruan
Copy link

@heruan heruan commented Sep 19, 2017

I'm migrating to 2.0.0 and I have a configuration annotated with @ConditionalOnBean({ Foo.class, Bar.class }) which should be evaluated as OR. How can I migrate this to AnyNestedCondition?

@wilkinsona
Copy link
Member Author

@wilkinsona wilkinsona commented Sep 19, 2017

@heruan Please see this comment above. You'd just use AnyNestedCondition rather than AllNestedCondition. If you have any further questions, please follow up on Stack Overflow or Gitter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants