icordoba
icordoba

Reputation: 1899

CDI: Dynamical injection of a group of classes how to?

I need to dynamically Inject a variable group of classes in my application. The purpose is, as the application grows, only have to add more classes inheriting the same interface. This is easy to do with tradicional java as I just need to search for all classes in a package and perform a loop to instantiate them. I want to do it in CDI. For example:

public MyValidatorInterface {
 public boolean validate();
}

@Named
MyValidator1 implements MyValidatorInterface
...

@Named
MyValidator2 implements MyValidatorInterface
...

Now the ugly non real java code just to get the idea of what I want to do:

public MyValidatorFactory {
 for (String className: classNames) {
  @Inject
   MyValidatorInterface<className> myValidatorInstance;
  myValidatorInstance.validate();
}
}

I want to loop over all implementations found in classNames list (all will be in the same package BTW) and Inject them dynamically so if next week I add a new validator, MyValidator3, I just have to code the new class and add it to the project. The loop in MyValidatorFactory will find it, inject it and execute the validate() method on the new class too.

I have read about dynamic injection but I can't find a way to loop over a group of class names and inject them just like I used to Instantiate them the old way.

Thanks

Upvotes: 1

Views: 503

Answers (1)

Siliarus
Siliarus

Reputation: 6753

What you are describing is what Instance<T> does.

For your sample above, you would do:

`@Inject Instance<MyValidatorInterface> allInstances`

Now, allInstances variable contains all your beans which have the given Type (MyValidatorInterface). You can further narrow down the set by calling select(..) based on qualifiers and/or class of bean. This will again return an Instance but with only a subset of previously fitting beans. Finally, you call get() which retrieves the bean instance for you.

NOTE: if you call get() straight away (without select) in the above case, you will get an exception because you have two beans of given type and CDI cannot determine which one should be used. This is implied by rules of type-safe resolution.

What you most likely want to know is that Instance<T> also implements Iterable so that's how you get to iterate over the beans. You will want to do something like this:

@Inject 
Instance<MyValidatorInterface> allInstances;

public void validateAll() {
  Iterator<MyValidatorInterface> iterator = allInstances.iterator();
  while (iterator.hasNext()) {
    iterator.next().callYourValidationMethod();
  }}
}

Upvotes: 3

Related Questions