Внедрение одного bean-объекта области видимости в другой bean-объект вида вызывает его воссоздание

Мне нужно использовать некоторые данные, сохраненные в bean-объекте видимости в другом bean-объекте видимости.

@ManagedBean
@ViewScoped
public class Attivita implements Serializable {
    //
}

а также

@ManagedBean
@ViewScoped
public class Nota implements Serializable {

    @ManagedProperty("#{attivita}")
    private Attivita attivita;

    // Getter and setter.
}

Теперь, может быть, моя теория об этом все еще довольно бедна, я заметил, что когда #{attivita} впрыскивается, Attivita конструктор вызывается и, таким образом, создает другой экземпляр. Это правильное поведение? Что если я захочу сослаться на тот же экземпляр, а не создать новый?

2 ответа

Решение

Это произойдет, если вы перемещаетесь от одного представления к другому при обратной передаче. Bean-объект области видимости связан не с запросом, а с видом. Поэтому, когда вы переходите к новому представлению, он получает совершенно новый экземпляр bean-объекта области видимости. Он не будет повторно использовать тот же экземпляр компонента, который связан с предыдущим представлением.

Я понимаю что attivita bean создается в начальном виде и повторно используется при обратной передаче. Я это понимаю nota bean связан с новым представлением, к которому вы переходите. При введении attivita в нем он просто получит новый и отличный экземпляр, даже если в том же запросе есть другой экземпляр. Это все ожидаемое (и по общему признанию немного не интуитивное) поведение.

Для этого не существует стандартного решения JSF. CDI решает это с @ConversationScoped (бин живет до тех пор, пока вы явно указываете ему жить), а расширение CDI MyFaces CODI идет немного дальше с @ViewAccessScoped (бин живет до тех пор, пока на него ссылается навигационное представление).

Однако вы можете обойти это, сохранив компонент в качестве атрибута в области запроса.

@ManagedBean
@ViewScoped
public class Attivita implements Serializable {

    public String submit() {
        FacesContext.getCurrentInstance().getExternalContext()
            .getRequestMap().put("attivita", this);
        return "nota";
    }

}

а также

@ManagedBean
@ViewScoped
public class Nota implements Serializable {

    private Attivita attivita;

    @PostConstruct
    public void init() {
        attivita = (Attivita) FacesContext.getCurrentInstance().getExternalContext()
            .getRequestMap().get("attivita");
    }

}

Обратите внимание, что это довольно хакерский. Могут быть лучшие решения в зависимости от конкретного функционального требования. Также обратите внимание, что вы должны в nota просмотреть ссылку желаемого Attivita экземпляр бина как #{nota.attivita} а не как #{attivita}потому что это даст вам новый и другой экземпляр, по причинам, уже объясненным ранее.

Ваш attivita боб @ViewScoped и это не гарантирует, что ваш экземпляр будет храниться в сессии. Тебе необходимо @SessionScoped боб. Тем не менее, если вам нужно attivita по какой-то причине @ViewScoped, затем вы можете передавать через них params другими способами, например, используя viewParam или используя другие @SessionScoped боб между ними.

Параметры страницы

http://mkblog.exadel.com/2010/07/learning-jsf2-page-params-and-page-actions/

JSF 2 управляемые бобовые области

http://balusc.blogspot.com.es/2011/09/communication-in-jsf-20.html

Другие вопросы по тегам