Добавить элементы в список с запросом Bean

У меня есть поддержка bean следующим образом:

@Named
@RequestScoped
public class ClientNewBackingBean {

    @Inject
    private ClientFacade facade;
    private Client client;

Класс Client имеет атрибут List<Child> childrenList, среди прочих. Я могу создать новый Client при установке childrenList с помощью new ArrayList().

В представлении у меня есть текстовое поле ввода и кнопка Add Child. Кнопка имеет атрибут actionListener=#{clientNewBackingBean.addChild()}, реализованный как:

public void addChild() {

    if(client.getChildrenList() == null) {
        client.getChildrenList(new ArrayList());
    }

    Child c = new Child("John Doe");

    client.getChildrenList().add(c);
}

Каждый раз, когда нажимается кнопка Add Child, воссоздается bean, и в представлении отображается только один дочерний элемент John Doe (из-за этого, я полагаю, из-за его запроса). Есть ли другой способ решить эту проблему, кроме изменения области bean на сеанс?

Ответ 1

Если вы использовали стандартную аннотацию управления bean JSF bean @ManagedBean, вы могли бы решить ее, просто разместив bean в области просмотра @ViewScoped.

@ManagedBean
@ViewScoped
public class ClientNewBackingBean implements Serializable {

    @EJB
    private ClientFacade facade;

    // ...

В CDI @ViewScoped, однако, не существует, ближайшая альтернатива @ConversationScoped. Вам нужно только начать и остановить его самостоятельно.

@Named
@ConversationScoped
public class ClientNewBackingBean implements Serializable {

    @Inject
    private Conversation conversation;

    // ...

    @PostConstruct
    public void init() {
        conversation.begin();
    }

    public String submitAndNavigate() {
        // ...

        conversation.end();
        return "someOtherPage?faces-redirect=true";
    }

}

Вы также можете использовать расширение CDI MyFaces CODI, который будет прозрачным образом аннотировать JSF @ViewScoped для правильной работы вместе с @Named

@Named
@ViewScoped
public class ClientNewBackingBean implements Serializable {

    @Inject
    private ClientFacade facade;

    // ...

Альтернативой CODI является использование @ViewAccessScoped, который живет до тех пор, пока последующие запросы ссылаются на тот же самый управляемый bean, независимо от используемого файла физического вида.

@Named
@ViewAccessScoped
public class ClientNewBackingBean implements Serializable {

    @Inject
    private ClientFacade facade;

    // ...

См. также:

Ответ 2

Если вы используете JSF 2, вы должны использовать ViewScoped bean.