Внедрение одного 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