В первую очередь создание компонента с new
обходит CDI и, естественно, инъекций не происходит .В этом причина NPE.
Вы можете решить проблему двумя способами: (1) Как вы говорите, составьте список управляемых CDI компонентов и добавьте его к тому, что запрашивает, или (2) сделать DemoView
простым Java-объектом, которым вы управляете, а не CDI, и при этом CDI по-прежнему создает и внедряет список таких вещей.
Solution 2
Solution (2)проще, и я бы поспорил более подходящим для некоторых случаев.Я не знаю точных деталей варианта использования, который приводит этот вопрос, но, очевидно, DemoView
является неким компонентом пользовательского интерфейса.При попытке использовать компоненты пользовательского интерфейса (например, JSF, JavaFX) в качестве компонентов CDI возникает серьезный конфликт: какая инфраструктура создаст объект?В любом случае измените DemoView
следующим образом:
// No scope annotation!
public class DemoView extends VerticalLayout {
// No inject!
private MessageBean messageBean;
public DemoView(MessageBean messageBean) {
this.messageBean = messageBean;
}
...
}
И производитель станет:
@ApplicationScoped
public class AppInitBean implements Serializable {
// Inject the collaborators required by DemoView here
@Inject
private MessageBean messageBean;
@Produces
@Named(value = "viewNamedList")
@ViewList
// I would argue you should define a scope here - @UIScoped maybe?
// This would be the scope of the produced list (and it seems appropriate)
public List<DemoView> getViews() {
return this.generateViews();
}
private List<DemoView> generateViews() {
List<DemoView> views = new ArrayList<DemoView>(5);
for (int i = 1; i <= 5; i++) {
DemoView emp = new DemoView(messageBean); // pass the messageBean
views.add(emp);
}
return views;
}
// You may also consider adding a disposer method,
// if the list of DemoViews needs special cleanup logic.
}
Если вы не предоставите область для созданных представлений, List
неявно@Dependent
-scoped.Будьте очень осторожны с этим , вам может потребоваться уничтожить его вручную, если его вводить в долгоживущий компонент (например, что-то @ApplicationScoped
).
Решение 1
Есливы действительно хотите получить решение (1), т. е. при создании списка управляемых bean-компонентов вы должны принять во внимание, что для bean-объектов нормальной области действия CDI сохраняет в активной области ровно 1 bean-компонент и не может управлять более (по крайней меребез классификаторов для разграничения экземпляров).Я догадываюсь , что @UIScoped
- это нормальная область.Если вы хотите сами управлять созданием боба, вы также должны (а) настроить его на @Dependent
и (б) самостоятельно управлять его жизненным циклом.Чтобы создать множество экземпляров bean-объекта в области @Dependent
, введите Instance<DemoView>
.
Итак, DemoView
изменится на:
@Dependent
public class DemoView extends VerticalLayout {
...
}
И производителя (общегоконцепция и непроверенный код, это может иметь незначительные ловушкиправильно !!!