JSF: почему пустой тест в отображаемом файле вызывается во время фазы применения значений запроса во время отправки формы в области запроса POST REDIRECT GET - PullRequest
2 голосов
/ 01 апреля 2012

Этот вопрос порожден из частичного ответа на JSF2: почему пустой рендеринг в рендеринге PanelGroup в составной части препятствует вызову действия?

В следующем элементе является @Сущность с именем и идентификатором.JSF-страница view.xhtml принимает идентификатор в качестве viewParam и использует setID (Long id) @ManagedBean @RequestScoped ElementController для запуска загрузки соответствующего элемента по id из базы данных (что не играет никакой дальнейшей роли в вопросе), и это находитЭлемент устанавливается как «текущий» элемент, доступный (по историческим причинам под немного другим именем) как элемент getSelected ().

Страница view.xhtml выполняет визуализованный атрибут test # {not empty elementController.selected} и имеет ah: commandButton с действием, которое выполняет перенаправление граней, вместе с id в качестве параметра запроса, обратно кview.xhtml page.

По какой-то причине я не до конца понимаю, что при отправке формы тест (и, следовательно, getSelected) вызывается как на этапе запроса на применение, так и на этапе проверки процесса, прежде чем идентификатор viewParam может бытьустановить (и, таким образом, до того, как текущий / выбранный элемент будет найден и установлен) на этапе обновления значений модели.

Очень сокращенная страница view.xhtml:

<f:view>
 <f:metadata>
    <f:viewParam name="id" value="#{elementController.id}"/>
 </f:metadata>
</f:view>
<h:body>   
 <h:form>
   <h:panelGroup rendered="#{not empty elementController.selected}">
       <h:outputText value="#{elementController.selected.name}"/>
   </h:panelGroup>

   <h:commandButton value="Apply" action="#{elementController.action}" />

 </h:form>
</h:body>

(смыслотправки формы выше, но это не имеет значения для этого вопроса.)

ElementController расширяет RequestController:

public void setId(Long id) {
log_debug("setId","id",id);
if (id != null) {
    this.id = id;
    T found = (T) getAbstractFacade().find(id);
    if (found == null) {
        String $error = "No object with id(" + id + ") found for class " + getManagedClass().getSimpleName();
        log_error($error);
    }
    setCurrent(found);
 }
}

public T getSelected() {
  log_debug("getSelected","current",current);        
  if (current == null) {
    log_warn("getSelected","null current Element");
   }
 return current;
}

public Object action() {
    String $i = "action";
    log_debug($i);
    if (current==null) {
        log_warn($i, "can't generate action outcome for null current element");
        return null;
    }
    return "/view?faces-redirect=true&id="+current.getId();
 }

Теперь при отправке формы getSelected () происходит вызываетсядважды, и когда current == null, один раз на этапах применения значений запроса и один раз на этапе проверки процесса, из-за to проверка # {не пустой elementController.selected} до установки идентификатора (и, следовательно, загрузки сущности Element) может произойти благодаря viewParam в view.xhtml.

Вопрос в том, почемуrendered = # {not empty elementController.selected}, который вообще вызывается на этапе применения запроса и на этапе проверки процесса?

Он не вызывается на этих этапах, когда я выполняю начальную загрузку GET файла view.xhtml сПараметр id, только во время отправки формы POST и последующего перенаправления и GET.

1 Ответ

4 голосов
/ 01 апреля 2012

Причина, по которой с атрибутом rendered обращаются дважды или более после постбэка, заключается в том, что JSF пересекает дерево компонентов на каждом этапе.

Имя 'rendered', возможно, не самое лучшее имя, так как оно не только делает рендеринг компонента, к которому он применяет, условным, но фактически обрабатывает его в целом.

Прежде всего, обращаются за «применением значений запроса», чтобы увидеть, нужно ли обрабатывать этот компонент и его дочерние элементы, чтобы применить к ним эти значения запроса. С ним снова обращаются в «процессах проверки», поскольку его значение могло изменяться между фазами.

Он не вызывается «во время тех фаз, когда я выполняю начальную загрузку GET», потому что когда вы выполняете GET, дерево компонентов не просматривается в этих фазах (обрабатываются только метаданные, что является причиной появления параметров представления в специальном разделе метаданных).

Чтобы сделать id, который вы получили из запроса GET, доступным в методе действия после публикации назад, лучше всего использовать область представления (@ViewScoped) для вашего компонента поддержки.

...