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

Allow autowiring of empty collection in @Bean method parameters using java.util.Optional [SPR-9132] #13771

Closed
spring-projects-issues opened this issue Feb 18, 2012 · 13 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Feb 18, 2012

Christopher Smith opened SPR-9132 and commented

The autowire semantics for collection types assume that at least one matching bean will be found to be injected. The new @Configuration syntax with parameter injection, however, does not have analog to @Autowired's required=false. Changing to field injection is an inelegant workaround, and it would be cleaner to have an @AllowEmpty or similar parameter annotation for the new syntax.


Affects: 3.1.1

Issue Links:

Referenced from: commits 7d22315

4 votes, 6 watchers

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Feb 18, 2012

Christopher Smith commented

I appear not to have permission to link to issue #11443, which addresses a similar concern with field injection. This issue is directed at the new @Configuration syntax:

@Bean public FooBean fooBean(BarBean barBean, Set<BazBean> bazBeans);

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

Hi Christopher,

You're correct that this represents a gap in support for autowired @Bean method parameters. However, while permitted, @Bean method parameter injection is relatively uncommon given that it renders the bean method un-invokable by other dependent @Bean methods. Couple that with the frequency of autowiring empty collections being itself relatively uncommon, this gap represents something of an edge case.

Also, the potential solutions here aren't great. @Bean method parameter semantics could be relaxed to always allow empty/null injection, but this would violate expectations for most users due to being the opposite of the way field/setter/constructor injection works; @Autowired's target element types could be relaxed to include parameters, but this would create confusion when at normal @Component setter and constructor injection points, creating ambiguity as to whether @Autowired should be placed at the method level or parameter level and the semantics for parameter-level injection in @Component cases would then need to be defined and possibly disallowed at runtime; finally, a new annotation could be invented for this purpose (as you suggest), but this is non-ideal because it does semantically overlap with the existing @Autowired/@Inject annotation support. Furthermore, adding a new annotation for what seems to be an infrequent use case is undesirable as it adds to the overall annotation 'surface area' of the framework -- one more thing for people to think about, read about in documentation, etc, when chances are they'll never use it.

So, given the reasons above combined with the fact that a reasonable (if somewhat inelegant for your purposes) workaround does exist, I'm leaving this open but moving it to the General Backlog where it can wait for further demand, e.g. votes and substantive comments. If we see a considerable number of folks wanting and needing this, we can revisit.

Thanks for taking the time in any case!

Chris

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

One additional option to consider here would be an attribute to the @Bean annotation itself, e.g.:

@Bean(requireParameters=false)
public FooBean fooBean(BarBean barBean, Set<BazBean> bazBeans) { ... }

This would then apply to both the barBean and bazBeans parameters, meaning that the container will inject null if no bean of type BarBean can be found and will inject an empty Set<BazBean> if not beans of type BazBean can be found. This is not exactly an 'elegant' approach either, but perhaps the best among the suggestions above. Again, we'll wait and see if this has any utility for other users.

@spring-projects-issues
Copy link
Collaborator Author

Michael Pellaton commented

We ran into this problem when we tried to declare a Netty ChannelGroup (a thread safe subtype of Set) as spring bean.

@spring-projects-issues
Copy link
Collaborator Author

Eirik Lygre commented

We totally need this :-)

Our application allows the customer to enable or disable various services. Other parts of the system then depends on those when creating higher-level services. Being able to mark parameters as optional would greatly simplify the code.

Also, while the suggested @Bean(requireParameters=false) is very easy to use, it may be insufficiently expressive. For example, the first parameter may be require, but the second not. I would therefore hope for an @Autowire-variant:

@Bean
public FooBean fooBean(BarBean barBean, @Autowired(required=false) Set<BazBean> bazBeans) { ... }

@spring-projects-issues
Copy link
Collaborator Author

Christopher Smith commented

As a revisit to this issue, what about just permitting @Optional on @Configuration beans? No new API, and AIUI standard semantics.

@spring-projects-issues
Copy link
Collaborator Author

Eirik Lygre commented

I'm not quite sure where the @Optional annotation comes from, but the idea is sound.

Another option (hah!) would be to allow/use java.util.Optional. This will not really help us right now (we're on java 7), but it would be yet another reason to move forward.

@spring-projects-issues
Copy link
Collaborator Author

Christopher Smith commented

java.util.Optional was what I had in mind. Spring already has support for it in other contexts.

@spring-projects-issues
Copy link
Collaborator Author

Ittai Zeidman commented

I actually have a similar demand but for all parameters not only collections. I'd like to get the "required = false" semantics on method parameters in @Bean methods. This is since we have the optional use-case quite often and we've found out that in complex scenarios using autowired members can cause spring to break with cyclic dependencies (our guess is that the member makes the entire @Configuration to depend on the member and not only the single method which needs it).
Additionally I don't want this to be a very coarse "let's make everything optional in this @Configuration file" but very fine-grained where a specific parameter on a specific @Bean can be made optional.
Would love to hear your feedback.

@spring-projects-issues
Copy link
Collaborator Author

Eirik Lygre commented

I very much agree, and I think I automatically assumed this issue covered both. I see now that it didn't, but second the idea that it should!

For a java.util.Optional based approach, this will be very natural: Optional<T> applies to any T, whether a collection or a single object:

@Bean
public FooBean fooBean(Optional<BarBean> barBean, Optional<Set<BazBean>> bazBeans) { ... }

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Oct 31, 2014

Juergen Hoeller commented

Note that basic support for java.util.Optional at injection points is available in Spring Framework 4.1 already; see #16452. I'm about to add specific unit tests for Optional usage in @Bean method signatures, including the use of collections, but would actually expect that to work already...

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Ittai Zeidman commented

@Juergen,
Can this be expanding to also supporting Scala's option?
We're also Java 7 but using mostly Scala so that would work for us.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

According to the new unit tests, this works fine in the 4.1.x line already, and is in line with our general java.util.Optional support in any case.

Supporting other ways of expressing optionality is worth considering - but let's do this in a separate JIRA issue for each specific style please.

Juergen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants