Снова я вижу, что @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?
Эта проблема имеет те же основания, что и ваш предыдущий вопрос, ответ на который дан здесь: Почему обратный вызов @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-тегов исключительно в бобах с масштабом запроса/сеанса/приложения, или поиск альтернативных способов для конкретного функционального требования. Вы можете заменить
на
, как вы уже выяснили.