2011-05-18 68 views
1

我想我遇到了Mojarra 2.1.0中的一個bug。也許我錯過了一些東西,但是如果我能看到它,該死的。使用JSTL /核心標籤擰起來ViewScoped Bean

我依靠很多@ViewScoped bean來保存狀態,同時瀏覽器爲服務器做了很多AJAX。我發現當我使用某些標記時,@ViewScoped bean在不應該出現時開始重新實例化。這裏是我的測試案例支持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頁:

<!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()調用來看到這一點。

如果將bean更改爲@SessionScoped,則不會發生這種情況。無論按鈕被點擊多少次,您都會獲得一個bean實例。但是,如果您將其保留爲@ViewScoped,並且您將c:foreach元素及其內容取出,則它現在不再重新實例化該bean的每次單擊。換句話說,它現在按預期工作。

這是一個莫哈拉錯誤還是我在這裏做錯了什麼?

回答

2

這是一個已知的「bug」:issue 1665。這是關於部分國家儲蓄的雞蛋問題。

然而,就你而言,你也可以使用<ui:repeat>

<ui:repeat value="#{testStuff.stuff}" var="x"> 
    <h:outputText value="#{x}" /> 
</ui:repeat> 

最好的辦法是在使用@ViewScoped時儘量避免使用JSTL標籤。唯一的選擇是通過上下文PARAM在web.xml禁用部分狀態保存:

<context-param> 
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name> 
    <param-value>false</param-value> 
</context-param> 

但它使意見更內存霸佔。

+0

我從ui開始:重複,但問題是它將整個集合視爲單個組件。換句話說,如果它在h:panelGrid中,您將得到一個包含一個單元格的表格。謝謝,雖然我認爲我可以解決這個問題,但它確實讓我發瘋,並且很高興知道這是一個真正的問題。 – AlanObject 2011-05-18 04:15:58