JSTL/核心标签的使用将ViewScoped Bean搞砸了 [英] Use of JSTL/core tags screws up ViewScoped Bean
问题描述
我认为我在Mojarra 2.1.0中遇到了一个错误.也许我错过了一些东西,但是如果我看得到就该死.
I think I have run into a bug in Mojarra 2.1.0. Maybe I missed something but damned if I can see it.
我依靠很多@ViewScoped bean来保存状态,而浏览器对服务器执行很多AJAX.我发现当我使用某些标签时,@ ViewScoped bean在不应该使用的时候开始重新实例化.这是我的测试用例支持bean:
I rely a lot of @ViewScoped beans to save state whilst the browser does a lot of AJAX to the server. I find when I use certain tags, the @ViewScoped bean starts getting re-instantiated when it shouldn't be. Here is my test case backing bean:
/*
* TestStuff.java
*/
package test;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
/**
* Backing bean for test.xhtml -- working out AJAX/SVG connection
*
*/
@ManagedBean
@ViewScoped
public class TestStuff implements Serializable {
private int counter = 0;
public TestStuff() {
log("TestStuff(): {0}", this);
}
public String getRandomNumber() {
int i = (int) (Math.random() * 1000000.0);
return String.format("%d", i);
}
public int getCounter() { return counter; }
public List<String> getStuff() {
return Arrays.asList("big", "bad", "wolf");
}
public void pushButton(ActionEvent evt) {
log("TestStuff.pushButton({0}): {1}",
new Object[] { evt, ++counter });
}
}
这是使用它的JSF Facelets页面:
And here is the JSF Facelets page that uses it:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<title>Test Page</title>
</h:head>
<h:body>
<h1>Test Page</h1>
<p>If you are reading this text, the server
is not properly configured.</p>
<ui:composition id="compRoot" template="/template5.xhtml">
<ui:define name="content">
<h1>Test</h1>
<h:form id="formTest">
<p:commandButton value="Do Me"
actionListener="#{testStuff.pushButton}"
update="testUpdate" />
<p:panel id="testUpdate" >
<h:outputText value="Random output is: " />
<h:outputText
value="#{testStuff.randomNumber}"
/>
<h:outputText value=" Counter is: "/>
<h:outputText
value="#{testStuff.counter}"
/>
</p:panel>
<h:panelGrid columns="5" border="1" >
<c:forEach items="#{testStuff.stuff}" var="x">
<h:outputText value="#{x}" />
</c:forEach>
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
这是哪里出了问题.当您单击"Do Me"命令按钮时,每次都会创建一个新的后备Bean实例,就像它是@RequestScoped Bean一样.我可以通过构造函数中的log()调用看到这一点.
So here is what goes wrong. When you click on the "Do Me" command button, a new instance of the backing bean gets created each time, just as if it were a @RequestScoped bean. I can see this via the log() call in the constructor.
如果将bean更改为@SessionScoped,则不会发生.无论单击按钮多少次,都可以获得一个Bean实例.
If you change the bean to @SessionScoped, this doesn't happen. You get one instance of the bean no matter how many times the button is clicked.
但是-如果将其保留为@ViewScoped,并取出 c:foreach 元素及其内容,则现在不再是每次单击都重新实例化Bean.换句话说,它现在可以按预期工作.
HOWEVER -- if you leave it as @ViewScoped, and you take out the c:foreach element and its content, it now no longer re-instantiates the bean each click. In other words it now works as expected.
这是mojarra的错误,还是我在这里做错了什么?
Is this a mojarra bug or am I doing something wrong here?
推荐答案
This is a known "bug": issue 1665. It's a chicken-egg issue with regard to partial state saving.
但是,您也可以只使用<ui:repeat>
.
In your case, however, you could also just use <ui:repeat>
.
<ui:repeat value="#{testStuff.stuff}" var="x">
<h:outputText value="#{x}" />
</ui:repeat>
您最好的选择是在使用@ViewScoped
时尽量避免使用JSTL标签.唯一的选择是通过web.xml
中的上下文参数禁用部分状态保存:
Your best bet is to try to avoid JSTL tags when using @ViewScoped
. The only alternative is to disable partial state saving by a context param in web.xml
:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
但是它使视图更多地占用了内存.
But it makes the views more memory hogging.
这篇关于JSTL/核心标签的使用将ViewScoped Bean搞砸了的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!