JSTL c:forEach заставляет @ViewScoped боб вызывать @PostConstruct на каждый запрос

Снова я вижу, что @PostConstruct стреляет каждый раз даже при том, что никакой обязательный атрибут не используется. См. этот код:-

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:c="http://java.sun.com/jsp/jstl/core">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <c:forEach var="item" items="#{TestBean.listItems}">
                <h:outputText value="#{item}"/>
            </c:forEach>
            <h:commandButton value="Click" actionListener="#{TestBean.actionListener}"/>
        </h:form>
    </h:body>
</html>

И это - самый простой боб в JSF:-

package managedBeans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean(name="TestBean")
@ViewScoped
public class TestBean implements Serializable {

    private List<String> listItems;

    public List<String> getListItems() {
        return listItems;
    }

    public void setListItems(List<String> listItems) {
        this.listItems = listItems;
    }

    public TestBean() {

    }

    @PostConstruct
    public void init(){
        System.out.println("Post Construct fired!");
        listItems = new ArrayList<String>();
        listItems.add("Mango");
        listItems.add("Apple");
        listItems.add("Banana");
    }

    public void actionListener(){
        System.out.println("Action Listener fired!");
    }

}

Вы видите поведение, которое должно заставить обратный вызов постконструкции стрелять каждый раз? Я думаю, что JSF 2.0 очень нестабилен. Если это должно запустить PostConstruct каждый раз, какая цель делает подачу @ViewScoped. Почему не использовать @RequestScoped только? Я думал, что сделал некоторую ошибку в своем приложении. Но когда я создал это самое простое в JSF, я все еще получаю эту ошибку. Разве я не понимаю объемов JSF? или разве они не тестируют его правильно? Далее, если Вы удаляете c:forEach и заменяете его ui:repeat, затем он хорошо работает.

При ожидании ответов, чтобы подтвердить, является ли это ошибкой или это является намеренным, чтобы мешать программистам использовать jstl?

8
задан BalusC 16 May 2010 в 02:42
поделиться

1 ответ

Эта проблема имеет те же основания, что и ваш предыдущий вопрос, ответ на который дан здесь: Почему обратный вызов @PostConstruct срабатывает каждый раз, даже если bean является @ViewScoped? JSF.

Это действительно ошибка в JSF2. Это проблема курицы и яйца. Скопированные бобы хранятся в состоянии представления JSF. Поэтому бобы, связанные с представлением, доступны только после восстановления фазы представления. Однако JSTL-теги запускаются во время фазы восстановления представления, в то время как скопированные бобы представления еще не доступны. Это приводит к созданию совершенно нового экземпляра скопированного боба представления, который затем заменяется реальным скопированным бином представления, который был сохранен в восстановленном состоянии представления JSF.

Об этом сообщается как JSF issue 1665 и JSF spec isssue 787, которые исправлены в JSF 2.2 и перенесены обратно в Mojarra 2.1.18. Таким образом, достаточно обновить Mojarra 2.1.18 до минимальной версии.

Если вы не можете обновиться, то лучшим вариантом будет использование JSTL-тегов исключительно в бобах с масштабом запроса/сеанса/приложения, или поиск альтернативных способов для конкретного функционального требования. Вы можете заменить на , как вы уже выяснили.

См. также:

13
ответ дан 5 December 2019 в 12:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: