在passthrough属性中访问迭代变量?

时间:2014-03-19 15:06:41

标签: jsf datatable jsf-2.2

我想知道为什么我会在下面找到NullPointerException

<h:dataTable value="#{testBean.entities}" var="d">
  <h:column p:data-order="#{d.modifiedOn}">
    <f:facet name="header">Date</f:facet>
    <h:outputText value="#{d.modifiedOn}">
      <f:convertDateTime pattern="#{msg.datePattern}" />
    </h:outputText>
  </h:column>    
</h:dataTable>

p命名空间为xmlns:p="http://xmlns.jcp.org/jsf/passthrough"modifiedOn为(非空)Date字段。

例外情况如下:

Caused by: java.lang.NullPointerException
    at com.sun.faces.renderkit.html_basic.HtmlResponseWriter.getAttributeValue(HtmlResponseWriter.java:1211)
    at com.sun.faces.renderkit.html_basic.HtmlResponseWriter.flushAttributes(HtmlResponseWriter.java:1171)
    at com.sun.faces.renderkit.html_basic.HtmlResponseWriter.closeStartIfNecessary(HtmlResponseWriter.java:1113)
    at com.sun.faces.renderkit.html_basic.HtmlResponseWriter.writeText(HtmlResponseWriter.java:936)
    at com.sun.faces.facelets.el.ELText$ELTextVariable.writeText(ELText.java:240)
    at com.sun.faces.facelets.compiler.TextInstruction.write(TextInstruction.java:85)
    at com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82)
    at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:302)
    at com.sun.faces.renderkit.html_basic.TableRenderer.renderHeader(TableRenderer.java:339)

但是,在#{d.modifiedOn}之类的任何非直通属性中使用headerClass都可以。与任何未在passthrough属性中引用迭代变量的值一样。

我的问题是:这是打算吗?

这是使用Wildfly-8.0.0.Final的JSF实现,版本2.2.5-jbossorg-3。

如果有人想知道:我正在尝试支持正交数据属性来增强我的表格。

编辑添加:我也尝试过,但是在<h:column>添加以下内容时遇到了相同的异常:

<f:passThroughAttribute name="data-order" value="#{d.modifiedOn}" />

这显然是由于JSF试图在rowIndex-1并且迭代数据尚未出现的标题上呈现此属性而引起的。所以对我的具体问题有一个黑客解决方案:

<h:column p:data-order="#{empty d or empty d.modifiedOn ? '' : d.modifiedOn.time}">
  ...
</h:column>

仍会在我的data-order中呈现空/无用的thead属性。

进一步测试: 更多的测试证实了我的怀疑,这只发生在任何列上的<f:facet name="header">(不必是具有该属性的列)。抛弃那些使我失败的目标是使用表作为数据表的基础,因为这需要一个格式良好的表<thead>

1 个答案:

答案 0 :(得分:1)

这是打算吗? Definitelly不是。此外,这里是根据JSF 2.2规范定义的passthrough属性:

  

传递属性

     

对于视图中的任何给定JSF组件标记,组件支持的可用属性集由a确定   该标记的UIComponent和Renderer的组合。在某些情况下,属性的值由解释   UIComponentor Renderer(例如,h:panelGrid的columns属性)和其他值的值   直接传递给用户代理(例如,h:inputText的lang属性)。

     

在这两种情况下,   UIComponent / Renderer具有允许属性集的先验知识。通过属性允许   视图作者列出直接传递给用户代理而没有解释的任意名称值对   由UIComponent / Renderer提供。在“渲染通过属性”中规范地指定了此行为   标准HTML_BASIC渲染工具包概述部分。

因此,这种属性的唯一功能是通知渲染器它必须处理属性的值,但它不依赖于任何UIComponent功能,因此必须以最终输出结束

我已经使用Tomcat 7 + Mojarra 2.2.6进行了测试,它对我来说非常适合。 HTML 元素使用其给定日期的数据顺序属性在DOM树中呈现。这是我用过的测试案例:

<html xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:p="http://xmlns.jcp.org/jsf/passthrough">
<h:head />
<h:body>
    <h:dataTable value="#{bean.entities}" var="entity">
        <h:column p:data-order="#{entity.modifiedOn}">
            #{entity.name}
        </h:column>
    </h:dataTable>
    <h:messages />
</h:body>
</html>
@ManagedBean
@ViewScoped
public class Bean {

    public class Entity {
        private String name;

        private Date modifiedOn;

        public Entity(String name, Date modifiedOn) {
            this.name = name;
            this.modifiedOn = modifiedOn;
        }

        public Date getModifiedOn() {
            return modifiedOn;
        }

        public String getName() {
            return name;
        }

    }

    /**
     * Create a List of entities with dates differing from now to now + 2 days
     */
    public List<Entity> entities = Arrays.asList(
            new Entity("name1", new Date()), new Entity("name2", new Date(
                    new Date().getTime() + (1000 * 60 * 60 * 24))), new Entity(
                    "name0", new Date(new Date().getTime()
                            + (1000 * 60 * 60 * 48))));

    public List<Entity> getEntities() {
        return entities;
    }

}

这意味着它是您的JSF实现中的一个错误(我不了解BTW的实现)。除非作者已经在以后的版本中修复过它,否则你最好打开一个bug轨道。

修改

当数据表涉及页眉或页脚f:facet时,渲染失败并显示给定错误。显然,Mojarra尝试在构建迭代器之前评估facet的passthrough值,这会导致它失败,因为变量尚不可用。打开issue

另见: