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

Enhancement Request - Allow @Bean to create managed Beans within Maps #32194

Closed
barrtrek opened this issue Aug 30, 2022 · 1 comment
Closed
Labels
status: duplicate A duplicate of another issue type: enhancement A general enhancement

Comments

@barrtrek
Copy link

barrtrek commented Aug 30, 2022

I am trying to create multiple beans of the same type using properties.yml and Properties classes annotated with
@ConfigurationProperties. I need most of my application flow to be externalized (without resorting to XML).

I've tried using Lists and Maps. Both work with binding to POJOs, but there's no way I've found to create these beans without some cumbersome post-processing. There are multiple StackOverflow questions trying to solve this problem in an elegant way.

Simple example:

public class Function(){

          public String name;

          <getters and setters>
}
@ConfigurationProperties(prefix = "function")
public class FunctionMapConfig(){

          public Map<String, Function> funmap;

          public List<Function>  funlist;

          @Bean
          @ConfigurationProperties(prefix = "function.mapbean")
          Map<String, Function> mapBean {
                   return new HashMap<String, Function>();
          }

         @Bean
         @ConfigurationProperties(prefix = "function.singlefun")
         Function singlefun(){
                  return new Function();
         }
          <getters and setters>
}
function:
      funmap:
          fun1:
              name: "function one"
          fun2:
              name: "function two"
      funlist:
          -   name: "function three"
          -   name: "function four"
      mapbean:
          fun5:
              name: "function five"
          fun6:
              name: "function six"
      singlefun:
              name: "function seven"
      

The top three of these methods work to create a collection POJOs of the Function class, but if I want them as managed beans for injection in other beans or for ease of management, I have to manually initialize and register them which is not ideal. The singlefun Bean is able to be created with PropertySource binding, but it can only create one and the yml does not let you have more than one singlefun: entry, no matter the scope definition.

I'd love to see @Bean enhanced to initialize the POJOs in the map as Beans with the key name as the bean name.
Something along these lines:

          @Bean(initializeCollectionClasses = true)
          @ConfigurationProperties(prefix = "function.mapbean")
          Map<String, Function> mapBean {
                   return new HashMap<String, Function>();
          }

I could see that even being a default behavior eventually.
It would be similar to the default behavior in @Autowiring existing beans into a Map where the Key becomes the name of the Bean.

ConfigurationProperties could also be altered to allow for prefixes like:

@Bean
@ConfigurationProperties(prefix = "function.listbean[]")

That way it would be clear that the collection elements are what should be initialized.
With the list, you'd also need the ability to indicate the bean name using one of the fields.

Ideally, you'd eventually be able to do dependent lists of beans from an externalized file.
Like so:

functions:
      google:
           url:  ...
      whitepages:
           url: ...
capabilities:
     finddinosaurs: 
           function: google
           queryString: "dinosaurs"
     findwhales:
           function: google
           queryString: "whales"
     findbob:
           function: whitepages
           queryString: "bob"

There may be some @DependsOn that would have to be added and you'd need a Converter to get the Functions beans for the Capability classes , but this seems like a very powerful way of externalization.

Let me know if I've missed some existing functionality, but this seems like a valuable ability.

@wilkinsona
Copy link
Member

Thanks for the suggestion.

Support for a single @Bean method defining multiple beans would be a Spring Framework enhancement as it provides support for @Configuration classes and the @Bean methods. It would then, perhaps, be possible for us to bind @ConfigurationProperties to those multiple beans but that would have to be built on top of whatever support Spring Framework provides.

#15732 is tracking auto-configuring multiple DataSources beans based using configuration properties, but we will want any solution for data sources to be general purpose so that it can work with beans of any type. I've updated the title of #15732 to reflect that broader scope and I am going to close this issue as a duplicate of it.

@wilkinsona wilkinsona closed this as not planned Won't fix, can't repro, duplicate, stale Aug 31, 2022
@wilkinsona wilkinsona added status: duplicate A duplicate of another issue type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Aug 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: duplicate A duplicate of another issue type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants