Мне нужно использовать некоторые данные, сохраненные в области с видимым охватом 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
вызывается и тем самым создает другой экземпляр. Это правильное поведение? А если я хочу ссылаться на один и тот же экземпляр, а не на новый?
Ответ 1
Это произойдет, если вы перейдете от одного к другому в обратном порядке. Область просмотра bean не привязана к запросу, а к представлению. Поэтому, когда вы переходите к новому представлению, он получит совершенно новый экземпляр области с охватом bean. Он не будет повторно использовать тот же экземпляр bean, который связан с предыдущим представлением.
Я понимаю, что attivita
bean создается в исходном представлении и повторно используется при обратной передаче. Я понимаю, что nota
bean связано с новым представлением, в которое вы переходите. При вводе attivita
в нем он просто получит новый и отдельный экземпляр, даже если в одном запросе есть еще один экземпляр. Это все ожидаемое (и, по общему признанию, немного неинтуитивное) поведение.
Для этого нет стандартного решения JSF. CDI решает это с помощью @ConversationScoped
(bean живет до тех пор, пока вы явно указываете, что он живет), а расширение CDI. MyFaces CODI немного отличается от @ViewAccessScoped
(bean живет до тех пор, пока ссылки навигации она).
Однако вы можете обойти это, сохранив bean как атрибут в области запроса.
@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
bean как #{nota.attivita}
, а не как #{attivita}
, потому что он предоставит вам новый и другой экземпляр по причинам, которые уже были объяснены ранее.
Ответ 2
Ваш attivita
bean - @ViewScoped
, и это не гарантирует, что ваш экземпляр будет удерживаться в сеансе. Вам нужен @SessionScoped
bean. Однако, если вам нужно attivita
по какой-то причине быть @ViewScoped
, тогда вы можете передавать параметры через них другими способами, например. используя viewParam
или используя другие @SessionScoped
bean между ними.
Параметр страницы
http://mkblog.exadel.com/2010/07/learning-jsf2-page-params-and-page-actions/
JSF 2 Управляемые bean Области
http://balusc.blogspot.com.es/2011/09/communication-in-jsf-20.html#ManagedBeanScopes