0

I have a vaadin UI class with a constructor taking 2 arguments. It builds a simple line with some fields, showing data. In another (parent) UI, I want to embed that first UI (child) multiple times, depending on some data loaded in the parent. So now I have two questions:

  1. Can I use springs @Autowired annotation to inject multiple instances of my child UI to the parent? If yes, how do I do this?
  2. How do I pass arguments to the constructor of my @Autowired child class?

I already found out, that I must annotate the constructor of my child class with @Autowired.

My child UI class with constructor (annotated with @Autowired)

public class ChildUI {

   private String arg1;
   private String arg2;

   @Autowired
   public ChildUI(String arg1, String arg2){
      this.arg1 = arg1;
      this.arg2 = arg2;
   }

}

In my parent class, I want to do something like this (personList is loaded from database):

public class ParentUI {

   ...
   for(Person p : personList){
      //inject instance of ChildUI here and pass p.getLastName() to arg1 and p.getFirstName() to arg2
   }
   ...

}

I googled for a while but I did not really find what I was looking for. Maybe I just don't know what keywords to search for. Can maybe someone try to explain what to do?

tigu
  • 731
  • 1
  • 7
  • 20

2 Answers2

1

Just create ChildUI like your normally would

  for(Person p : personList){
     ChildUI someChild=nChildUI(p.getLastName(),m.getFirstName());
   }
   ...

and do something with someChild

Or if ChildUI have some other dependencies injected - first make it prototype scoped, then

    @Autowire
    private ApplicationContext ctx;
....
      for(Person p : personList){
         ChildUI someChild=ctx.getBean(ChildUI.class,p.getLastName(),m.getFirstName());
       }
Antoniossss
  • 31,590
  • 6
  • 57
  • 99
  • Ok, I will try this tomorrow. At the moment, I create the ChildUIs as you propose: `ChildUI child = new ChildUI(p.getLastName(), p.getFirstName());`. Now I need to inject a CrudRepository in ChildUI. So if I make it prototype scoped, I can use injected (@Autowire'd) beans in ChildUI and still create multiple instances of it? – tigu Oct 13 '19 at 21:58
  • 1
    Yes - in that case you must use the second snippet with ApplicationContext. If ChildUI wil be a prototype, new instance will be returned on every call. – Antoniossss Oct 14 '19 at 07:34
  • Hey Antoniossss, thank you for support. I tried it this evening but I think I still got something wrong. In ParentUI, I added a `private ApplicationContext ctx` and I am creating the instances of my ChildUI with `layout.add(ctx.getBean(ChildUI.class, Person p));` (I decided to pass the whole object because I want to do some stuff with it). In my ChildUI I have the following annotations: `@Scope("prototype")`and `@SpringComponent`. When I now use `Person p`in ChildUIs constructor, I still get a `NullPointerException`. What am I missing? Something about Person instances (created with new ...)? – tigu Oct 14 '19 at 17:41
  • I just got it now :-) My mistake was, that I used another bean, which was injected with `@Autowired` in ChildUIs constructor. I moved it to a `@PostConstruct` method and now it works just perfectly. – tigu Oct 14 '19 at 20:07
  • 1
    Ye, setter and field injections happen after constructor injection and call so yes you cannot use those dependcies at that point. @PostConstruct is the way to go (or injection of all dependencies in ctor). – Antoniossss Oct 14 '19 at 20:21
1

I'm not sure I completely understand what you ask, so let me know if that's not what you meant.

Creating multiple instances of your childUI: This is simple, create multiple beans in your configuration class:

@Configuration
public class ApplicationConfiguration {

  @Bean
  public ChildUI firstBean(){
    return new ChildUI(arg1,arg2);
  }

  @Bean
  public ChildUI secondBean(){
    return new ChildUI(otherArg1,otherArg2);
  }

  @Bean
  public ChildUI thirdBean(){
    return new ChildUI(arg1,arg2);
  }
}

multiple instances injected to other bean: If you autowire a set (or list) of the type of your bean, all instances of it will be injected to it:

public class ParentUI {

  private final Set<ChildUI> children;

  @Autowired
  public ParentUI(Set<ChildUI> children) {
    this.childern = children;//this will contain all three beans
  }
}
Nir Levy
  • 12,750
  • 3
  • 21
  • 38
  • Thank you, I did not know the possibility to inject a Set like this. The problem with your proposal is, that the number of ChildUI's is not static, but depends on the user's iput in ParentUI. So I can not finally define the list of ChildUIs in the Configuration class. – tigu Oct 13 '19 at 21:57