JEE - добавить список бобов - PullRequest
       24

JEE - добавить список бобов

0 голосов
/ 29 ноября 2018

Я хотел бы добавить список бобов.Я искал в сети, но нашел не очень.Я пробовал это: https://onlysoftware.wordpress.com/2011/07/10/injecting-lists-cdi-jsf/ но с бобами.

Вид:

@UIScoped
public class DemoView extends VerticalLayout {

    @Inject
    private MessageBean messageBean;

    private Button button;

    public DemoView() {
        getStyle().set("border", "1px solid");
        button = new Button("Click me", event -> Notification.show(messageBean.getMessage()));
    }

    public void init() {
        removeAll();
        add(new Label("oh no!"));
        add(button);
    }
}

Аннотация:

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier
public @interface ViewList {
}

InitBean:

@ApplicationScoped
public class AppInitBean implements Serializable {

    @Produces
    @Named(value = "viewNamedList")
    @ViewList
    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();
            views.add(emp);
        }
        return views;
    }
}

MainClass:

@Route("")
public class MainView extends VerticalLayout implements BeforeEnterObserver {

    @Inject
    @ViewList
    private List<DemoView> viewList;

    @Override
    public void beforeEnter(BeforeEnterEvent event) {
        removeAll();
        add(new Label("whatever"));
        for (DemoView demoView : viewList) {
            demoView.init();
            add(demoView);
        }
    }
}

Список составлен и будет отображаться так, как ожидается.Но если я нажимаю кнопку, я получаю NPE -> messageBean не вводится.

Итак, мой вопрос: возможно ли даже добавить список bean-компонентов?Я полагаю, если это возможно, также должно быть возможно добавить элемент в список.Но один шаг за другим.

1 Ответ

0 голосов
/ 29 ноября 2018

В первую очередь создание компонента с 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 {
    ...
}

И производителя (общегоконцепция и непроверенный код, это может иметь незначительные ловушкиправильно !!!

...