Как (и когда?) Удалить область сеанса bean в JSF 2.0

Фон: у меня есть приложение JSF 2.0 с использованием MyFaces. Используя это приложение, пользователи создадут сложный "Виджет", пройдя через несколько разных страниц JSF. Я храню управляемый bean в области сеанса, и свойства заполняются, когда пользователь просматривает каждую страницу. После того, как они будут собраны "виджет", они захотят создать новый "виджет" и повторить этот процесс. Мой вопрос: как полностью (и безопасно) удалить управляемый bean из сеанса без нарушения жизненного цикла JSF?

Я видел другие ответы на подобные вопросы, предлагая вам аннулировать сеанс, а также вы можете получить доступ к HttpSession через FacesContext и удалить bean таким образом. Я не хочу, чтобы пользователь должен был выйти из системы или снова, и я не хочу отменять весь сеанс. Предполагая, что мне нужно пройти через FacesContext, чтобы получить доступ к HttpSession и удалить bean, когда в JSF lifecyle является наиболее подходящим местом, чтобы сделать это безопасно, чтобы проблемы не каскадировались через оставшуюся часть цикла? Я хочу убедиться, что у JSF не возникнет проблем с созданием нового сеанса bean, когда пользователь начнет процесс создания следующего "виджета".

Мне также интересно узнать, почему в JSF нет механизма, чтобы сделать это проще. Есть ли какой-то другой подход, который я должен принимать, который лучше соответствует намеченному шаблону JSF? Я не могу использовать View Scope здесь, потому что управляемый bean будет проходить через несколько разных страниц и представлений до его завершения.

Спасибо в Advance!

Ответ 1

Создайте одну страницу, в которой вы выполняете несколько шагов мастера.

<h:panelGroup rendered="#{wizard.step == 1}">
   <ui:include src="/WEB-INF/wizard/step1.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{wizard.step == 2}">
   <ui:include src="/WEB-INF/wizard/step2.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{wizard.step == 3}">
   <ui:include src="/WEB-INF/wizard/step3.xhtml" />
</h:panelGroup>

Таким образом, вы можете просто использовать @ViewScoped управляемый bean на этой странице без особых проблем.


Не привязанный к конкретному вопросу, PrimeFaces имеет <p:wizard>, что почти так. Вы можете найти это полезным для того, чтобы спасти себя от какого-то болезненного кода шаблона, который касается валидации и т.д.

Ответ 2

Ваш случай может быть упрощен, если данные создания виджета инкапсулированы в один bean. Я имею в виду

@SessionScoped
@ManagedBean
public class WidgetMaker {
  private Widget widget;

  public void makeWidget(){
   //after creating/saving widget
    widget = new Widget();
  }

  public void resetWidget(){
    //this method can be called with pre render view handler
    //call this method on the first page that starts widget creation
    //in case person leaves the widget creation in between and starts over again
    widget = new Widget();
  }
}

Для просмотра resetWidget (только на первой странице создания виджета)

<f:metadata>
  <f:event type="preRenderView" listener="#{widgetMaker.resetWidget}"/>
</f:metadata>

Вы можете принимать указатели и соответственно адаптироваться.

Надеюсь, что это поможет.

Ответ 3

Хотя я еще не использовал его сам, я бы посмотрел на CDI ConversationScope.

Ответ 4

Я согласен с BalusC в том, что область обзора будет лучшим выбором в вашем случае. Я просто посмотрел на мой (очень старый) первый проект JSF, где у меня была многостраничная форма в области сеанса. Позже я перешел в режим просмотра по известным причинам.

Однако, я сделал reset сеансовую область bean, просто заменив экземпляр на карте сеанса:

MyBean newInstance = new MyBean();
FacesContext.getCurrentInstance().getExternalContext()
   .getSessionMap().put(beanName, newInstance);

с beanName как имя bean el (строка).