关于雅加达ee:PrimeFaces数据表:使用GlassFish Mojarra由ClassCastException(无stacktrace)引起的奇怪ELException

PrimeFaces dataTable: strange ELException caused by ClassCastException (no stacktrace) using GlassFish + Mojarra

我们有一个碰撞实体列表,您可以在PrimeFaces <p:datatable>中进行单选。在该字段的下面是一个字段集,该字段集显示了相关的历史记录和文件附件。

这是JSF页面(附件数据表比其他数据表更重要):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<h:panelGrid>

    <p:scrollPanel mode="native">
        <p:dataTable value="#{collisionManager.selectedCollisions}"
                     var="cln"
                     selection="#{collisionManager.selectedStateChangeCollision}"
                     selectionMode="single"
                     rowKey="#{cln.id}"
                     paginator="true"
                     paginatorPosition="bottom"
                     rows="5">

            <p:ajax event="rowSelect" process="@this" update="@form" />

            <p:column headerText="ID">
                <h:outputText value="#{cln.id}" />
            </p:column>

            ...

        </p:dataTable>
    </p:scrollPanel>

    <p:fieldset legend="History and Attachments">

        <p:tabView widgetVar="stateChangeTabView"
                   dynamic="true"
                   cache="false">

            <p:tab title="History">
                ...
            </p:tab>

            <p:tab title="Attachments">
                <p:dataTable id="attachments-datatable"
                             value="#{attachmentManager.activeAttachments}"
                             var="att"
                             paginator="true"
                             paginatorPosition="bottom"
                             rows="3">

                    <p:column headerText="File Name">
                        <h:outputText value="#{att.fileName}" />
                    </p:column>

                    <p:column headerText="Deleted">
                        <h:outputText value="#{att.deleted}" />
                    </p:column>

                    <p:column headerText="Marked">
                        <h:outputText value="#{attachmentManager.markedToDelete(att)}" />
                    </p:column>

                    <p:column headerText="Actions">
                        <p:commandButton icon="ui-icon ui-icon-trash"
                                         title="Mark to delete"
                                         action="#{attachmentManager.markToDelete(att)}"
                                         process="@this"
                                         update="@form"
                                         rendered="#{not attachmentManager.markedToDelete(att)}">
                        </p:commandButton>
                        <p:commandButton icon="ui-icon ui-icon-cancel"
                                         title="Unmark to delete"
                                         action="#{attachmentManager.unmarkToDelete(att)}"
                                         process="@this"
                                         update="@form"
                                         rendered="#{not attachmentManager.markedToDelete(att)}">
                        </p:commandButton>
                    </p:column>
                </p:dataTable>
            </p:tab>

        </p:tabView>

    </p:fieldset>

</h:panelGrid>

<!-- SAVE + CANCEL buttons here -->

这里是AttachmentManager bean(@Named@Viewscoped兼容的类路径上有Seam 3 Faces,在这里无关紧要):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Named
@ViewScoped
public class AttachmentManager implements Serializable
{
    // attachments to be deleted
    private List<Attachment> markedAttachments;

    public void markToDelete( Attachment attachment )
    {
        if ( !this.markedAttachments.contains( attachment ) )
        {
            this.markedAttachments.add( attachment );
        }
    }

    public void unmarkToDelete( Attachment attachment )
    {
        this.markedAttachments.remove( attachment );
    }

    public boolean markedToDelete( Attachment attachment )
    {
        return this.markedAttachments.contains( attachment );
    }
}

在行(附件表)的页面上评估表达式时,问题开始:

1
<h:outputText value="#{attachmentManager.markedToDelete(att)}" />

上面的代码中实际执行哪个表达式都没有关系,它们基本上都会失败:

1
javax.el.ELException: /view/changeData.xhtml @184,102 value="#{not attachmentManager.markedToDelete(att)}": java.lang.ClassCastException: com.company.project.model.Attachment cannot be cast to com.company.project.model.Collision

请注意,绝对没有堆栈跟踪-至少不是我能够找到一个。我什至查看了服务器响应(AJAX),发现其中有些异常有时会被吞没-没事。

我发现了另外两个与我的问题有关的帖子(也未解决):

http://forum.primefaces.org/viewtopic.php?f=3


我用版本2.1.14交换了服务器的Mojarra,在几次重载/重试之后,堆栈跟踪终于出现了。 (在最初的几次尝试中都是一样的,也许GlassFish会缓存其JAR的相关部分)

在那之后,它变得非常容易:我将equals方法从Collision复制到了Attachment,并保留了对Collision的强制转换。这就是导致CCE的原因。

但是,这仍然是一个谜,堆栈跟踪将继续下去...