selectoneitem上的AJax Callback失败(NPE)

时间:2013-01-03 10:38:09

标签: ajax jsf-2 nullpointerexception jboss7.x

使用this StackOverflow answer尝试实现无提交表单。该页面由selectomenu控件和表组成。在改变选择时我希望刷新表体。页面加载没有问题,但是当做出选择时,我发生以下错误:

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);
    }
    }
}

2 个答案:

答案 0 :(得分:3)

你的堆栈跟踪看起来不完整,因为它实际上并没有引用你的代码(这是我希望抛出npe的地方)。尽管如此,您的选择菜单没有转换器,所以除了任何其他问题,您的表单可能仍然无法保存或注册选择

  1. 实现JSF转换器并在该selectonemenu上声明它。当选择类型组件需要选择并保存复杂的POJO类型时,这是必需的您可以查看this example

  2. 尝试摆脱标记中的巨大<h:form/>。该表单中有太多其他组件可能会导致您出现问题。将组件分成不同形式的小块

答案 1 :(得分:0)

如果bean的范围是@RequestScoped,那么将其更改为@ViewScoped,通常使用@ViewScoped更好地完成ajax ...导致在每次提交时创建的bean的新实例...

@ManagedBean(name="shipManager")
@ViewScoped

另外,请确保changeShip方法将AjaxBehaviorEvent作为参数

(即)

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

并且还指定了f:Ajax

中的execute和Render属性
<f:ajax  execute="ship" render="@form"  listener="#{shipManager.changeShip}" />