2013-01-03 92 views
0

使用this StackOverflow answer嘗試執行無提交形式。該頁面由一個selectomenu控件和一個表格組成。關於選擇的更改,我希望刷新表格主體。該頁面加載沒有問題,但是當選擇時我得到出現以下錯誤:在selectoneitem上的AJax回調失敗(NPE)

10:22:48,241 ERROR [[FacesServlet]] Servlet.service() for servlet FacesServlet threw exception: java.lang.NullPointerException 
    at com.sun.faces.context.PartialViewContextImpl.createPartialResponseWriter(PartialViewContextImpl.java:441) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at com.sun.faces.context.PartialViewContextImpl.access$300(PartialViewContextImpl.java:71) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at com.sun.faces.context.PartialViewContextImpl$DelayedInitPartialResponseWriter.getWrapped(PartialViewContextImpl.java:582) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at javax.faces.context.PartialResponseWriter.startDocument(PartialResponseWriter.java:115) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at com.sun.faces.context.AjaxExceptionHandlerImpl.handlePartialResponseError(AjaxExceptionHandlerImpl.java:199) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at com.sun.faces.context.AjaxExceptionHandlerImpl.handle(AjaxExceptionHandlerImpl.java:123) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:119) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:116) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:] 
    at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final] 
    at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final] 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:505) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:445) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:] 
    at java.lang.Thread.run(Thread.java:636) [rt.jar:1.6.0_18] 

我使用JBoss的AS-7.1.1,和selectonmenu看起來是這樣的:

<h:selectOneMenu id="ship" 
      value="#{shipManager.current}"> 
    <f:selectItems value="#{shipManager.list}" 
       var="ship" 
       itemValue="#{ship}" 
       itemLabel="#{ship.name}" /> 
    <f:ajax listener="#{shipManager.changeShip}" /> 
</h:selectOneMenu> 

如果我刪除ajax組件然後沒有問題,雖然(當然)shipManager未更新。

一旦我做了選擇,我想添加renderer部分來刷新我的表體。

非常感謝任何幫助。

史蒂夫

如這裏要求是我的XHTML代碼:

<?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:f="http://java.sun.com/jsf/core" 
     xmlns:h="http://java.sun.com/jsf/html" 
     xmlns:ui="http://java.sun.com/jsf/facelets"> 

    <h:head> 
    <title>Voyage Cruises</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 
    <link type="text/css" rel="stylesheet" media="all" href="/css/screen.css"/> 
    <link type="text/css" rel="stylesheet" media="all" href="/css/cruise.css"/> 
    <script src="http://open.mapquestapi.com/sdk/js/v7.0.s/mqa.toolkit.js"></script> 
    <script src="js/map.js" ></script> 
    <script src="js/cruise.js" ></script> 
    </h:head> 

    <h:body> 
    <div id="page"> 
     <div id="float-map"> 
    <div id="map"></div> 
     </div> 

     <h:form id="ship-form"> 

    <div id="ship-controls"> 
     <div class="float-ctrls"> 
     <a href="/ports.html" title="Find Ports"><img src="/images/action_search.png" alt="Find Ports"/></a> 
     </div> 
     <div> 
     <span id="ship-selector" > 
      <h:selectOneMenu id="ship" 
        value="#{shipManager.current}"> 
     <f:selectItems value="#{shipManager.list}" 
        var="ship" 
        itemValue="#{ship}" 
        itemLabel="#{ship.name}" /> 
     <f:ajax execute="ship" render="@form" listener="#{shipManager.changeShip}" /> 
      </h:selectOneMenu> 
     </span> 
     <select id="month" /> 
     <select id="year" /> 
     <br /> 
     <span class="input-container"><b>Tonnage:</b><input id="tonnage" type="text" size="6" value="30,277" /></span> 
     <span class="input-container"><b>Audit Time:</b><input id="audit" type="text" size="2" value="6" /></span> 
     <span class="input-container"><b>Fleet:</b><input id="fleet" type="text" size="20" value="P&amp;O" /></span> 
     </div> 
    </div> 

    <table class="cruise"> 
     <thead> 
     <tr> 
      <th class="date">Date</th> 
      <th class="port">Port</th> 
      <th class="arrive">Arrive</th> 
      <th class="depart">Depart</th> 
     </tr> 
     </thead> 
     <tbody> 
     <ui:repeat var="cruise" 
       value="#{cruiseManager.list}" 
       varStatus="table"> 
      <tr class="#{table.even ? 'even' : 'odd'}"> 
     <td class="date"> 
      <h:outputFormat value="{0, date,d MMM}"> 
      <f:param value="#{cruise.date}" /> 
      </h:outputFormat> 
     </td> 
     <h:panelGroup rendered="#{null != cruise.port}"> 
      <td class="port">#{cruise.port.name}</td> 
      <td class="arrive"> 
      <h:outputFormat rendered="#{null != cruise.arrival}" 
        styleClass="#{cruise.arrivalEstimated ? 'est-time' : 'act-time'}" 
        value="{0, date,HH:mm}"> 
       <f:param value="#{cruise.arrival}" /> 
      </h:outputFormat> 
      </td> 
      <td class="depart"> 
      <h:outputFormat rendered="#{null != cruise.departure}" 
        styleClass="#{cruise.departureEstimated ? 'est-time' : 'act-time'}" 
        value="{0, date,HH:mm}"> 
       <f:param value="#{cruise.departure}" /> 
      </h:outputFormat> 
      </td> 
     </h:panelGroup> 
     <h:panelGroup rendered="#{null == cruise.port}"> 
      <td class="at-sea" colspan="3">At Sea</td> 
     </h:panelGroup> 
      </tr> 
     </ui:repeat> 
     </tbody> 
    </table> 

     </h:form> 
    </div> 
    </h:body> 
</html> 

而且ShipManager:

package com.nutrastat.voyager.web; 

import java.io.Serializable; 
import java.util.ArrayList; 
import java.util.List; 

import javax.ejb.EJB; 
import javax.faces.bean.ManagedBean; 
import javax.faces.bean.ViewScoped; 
import javax.faces.event.AjaxBehaviorEvent; 

import com.nutrastat.voyager.db.HarbourMasterLocal; 
import com.nutrastat.voyager.db.ShipEntity; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

@ManagedBean 
@ViewScoped 
public class ShipManager 
    implements Serializable { 

    static final long serialVersionUID = -3017226836104715117L; 

    private transient final Logger log; 

    private ShipEntity currentShip; 

    @EJB 
    private HarbourMasterLocal harbourMaster; 

    public ShipManager() { 
    log = LoggerFactory.getLogger(getClass()); 
    } 

    public ShipEntity getCurrent() { 
    if (log.isInfoEnabled()) 
     log.info("getCurrent(): " + currentShip); 
    return currentShip; 
    } 

    public void setCurrent(ShipEntity ship) { 
    if (log.isInfoEnabled()) 
     log.info("setCurrent(" + currentShip + "): " + ship); 
    currentShip = ship; 
    } 

    public void changeShip(AjaxBehaviorEvent evt) { 
    if (log.isInfoEnabled()) 
     log.info("Ship now: " + currentShip); 
    } 

    public List<ShipEntity> getList() { 
    try { 
     return harbourMaster.listShips(); 

    } catch (Exception cause) { 
     log.error("Getting the list of ships", cause); 
     return new ArrayList<ShipEntity>(0); 
    } 
    } 
} 

回答

3

你的堆棧跟蹤看起來不完整,因爲它實際上並沒有引用你的代碼(這是我期望的npe被拋出的地方)。儘管如此,你的選擇菜單沒有一個轉換器,所以任何其他問題不談,你的形式很可能仍然無法保存或註冊的選擇

  1. 實現一個JSF轉換器,並宣佈其對selectOneMenu用於。當選擇類型組件需要選擇並保存複雜的POJO類型時,這是必需的。您可以看看this example

  2. 試圖擺脫標記中那個巨大的<h:form/>。這種形式中有太多其他組件可能會導致您的問題。將組件拆分爲更小的塊(以單獨的形式)

+0

嗨。我的堆棧跟蹤可能看起來不完整,但它就是這樣。由於我不需要存儲POJO,因此我將selectOneMenu轉換爲僅使用字符串。這並刪除尚未使用(但將需要)的其他選擇項目清除錯誤,現在一切正常。非常感謝。 – Dobbo

0

如果你的bean的範圍@RequestScoped然後將其更改爲@ViewScoped ,通常ajax最好用@ViewScoped來完成...導致每次提交時創建的bean的新實例...

@ManagedBean(name="shipManager") 
@ViewScoped 

同時確保changeShip方法需要AjaxBehaviorEvent作爲參數

(IE)

public void changeShip (AjaxBehaviorEvent event){ 
//** do your stuf 
} 

也specidy的執行和渲染內˚F屬性:阿賈克斯

<f:ajax execute="ship" render="@form" listener="#{shipManager.changeShip}" /> 
+0

我的changeShip()方法沒有AjaxBehaviourEvent參數,但現在可以。該bean的範圍是SessionScoped,但是和ViewScoped都會導致錯誤。 – Dobbo

+0

您是否還在f:ajax中添加了執行和渲染屬性,如答案中指定的那樣?如果你正在使用ajax更好的使用@ViewScoped本身..我做了 –

+0

,但它仍然導致異常。 – Dobbo