javax.el.ELException:java.lang.UnsupportedOperationException 在 java.util.AbstractList.add

javax.el.ELException: java.lang.UnsupportedOperationException at java.util.AbstractList.add

在 Wildfly 9(JSF 2.2、EL 3.0)上,我有两个嵌套的 <ui:repeat> 标签,想使用外部标签的 var 属性作为内部标签的方法参数:

<ui:repeat value="#{bean.getEntries()}" var="entry">
    <ui:repeat value="#{bean.getPosts(entry)}" var="post">
        <p id="text">#{post.text}</p>
    </ui:repeat>
</ui:repeat>

bean.getEntries() returns List<Entry>bean.getPosts(Entry entry) returns List<Post> 正如人们所期望的那样。

但是我得到了一个例外,而不是一些 <p> 充满帖子的标签:

11:24:26,574 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (default task-2) Error Rendering View[/index.xhtml]: javax.el.ELException: /WEB-INF/templates/diary.xhtml @14,73 value="#{sessionBean.getPublicPosts(elEntry)}": java.lang.UnsupportedOperationException
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114)
at com.sun.faces.facelets.component.UIRepeat.getValue(UIRepeat.java:279)
at com.sun.faces.facelets.component.UIRepeat.getDataModel(UIRepeat.java:255)
at com.sun.faces.facelets.component.UIRepeat.setIndex(UIRepeat.java:523)
at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:577)
at com.sun.faces.facelets.component.UIRepeat.encodeChildren(UIRepeat.java:1110)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at com.sun.faces.facelets.component.RepeatRenderer.encodeChildren(RepeatRenderer.java:104)
at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:621)
at com.sun.faces.facelets.component.UIRepeat.encodeChildren(UIRepeat.java:1110)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:456)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:133)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:655)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:86)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:72)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:282)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:261)
at io.undertow.servlet.handlers.ServletInitialHandler.access[=14=]0(ServletInitialHandler.java:80)
at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:172)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:199)
at io.undertow.server.HttpServerExchange.run(HttpServerExchange.java:774)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.el.ELException: java.lang.UnsupportedOperationException
at javax.el.ELUtil.invokeMethod(ELUtil.java:312)
at javax.el.BeanELResolver.invoke(BeanELResolver.java:537)
at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:256)
at com.sun.el.parser.AstValue.getValue(AstValue.java:136)
at com.sun.el.parser.AstValue.getValue(AstValue.java:204)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:226)
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
... 49 more
Caused by: java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at org.bollin.diary.util.SessionBean.getPublicPosts(SessionBean.java:124)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at javax.el.ELUtil.invokeMethod(ELUtil.java:308)
... 57 more

11:24:26,580 ERROR [io.undertow.request] (default task-2) UT005023: Exception handling request to /diary/index.jsf: javax.servlet.ServletException
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:667)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:86)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:72)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:282)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:261)
at io.undertow.servlet.handlers.ServletInitialHandler.access[=14=]0(ServletInitialHandler.java:80)
at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:172)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:199)
at io.undertow.server.HttpServerExchange.run(HttpServerExchange.java:774)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at org.bollin.diary.util.SessionBean.getPublicPosts(SessionBean.java:124)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at javax.el.ELUtil.invokeMethod(ELUtil.java:308)
at javax.el.BeanELResolver.invoke(BeanELResolver.java:537)
at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:256)
at com.sun.el.parser.AstValue.getValue(AstValue.java:136)
at com.sun.el.parser.AstValue.getValue(AstValue.java:204)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:226)
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
at com.sun.faces.facelets.component.UIRepeat.getValue(UIRepeat.java:279)
at com.sun.faces.facelets.component.UIRepeat.getDataModel(UIRepeat.java:255)
at com.sun.faces.facelets.component.UIRepeat.setIndex(UIRepeat.java:523)
at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:577)
at com.sun.faces.facelets.component.UIRepeat.encodeChildren(UIRepeat.java:1110)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at com.sun.faces.facelets.component.RepeatRenderer.encodeChildren(RepeatRenderer.java:104)
at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:621)
at com.sun.faces.facelets.component.UIRepeat.encodeChildren(UIRepeat.java:1110)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:456)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:133)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:655)
... 27 more
java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(AbstractList.java:148)
    at java.util.AbstractList.add(AbstractList.java:108)
    at org.bollin.diary.util.SessionBean.getPublicPosts(SessionBean.java:124)

SessionBean class的第124行中使用的List实现,在getPublicPosts()方法中,不支持调用add()方法.

当它是一个不可修改的列表时,例如 Collections#unmodifiableList() and Arrays#asList() 返回的列表,就会发生这种情况。

在修改之前将其包装在可修改列表中。

modifiableList = new ArrayList<>(unmodifiableList);

请注意,此问题与 JSF 或 EL 没有严格关系,它只是基本问题 Java。您可以使用带有 main() 方法的简单 Java 应用程序 class 重现完全相同的问题。在以后的问题中,首先这样做是明智的,以便将 JSF/EL 排除在可能的原因之外。


与具体问题无关,这表明另一个设计问题:在 Javabean getter 方法中执行业务逻辑。这是性能明智的一个非常糟糕的主意,因为它在每个迭代轮次期间调用的这个特定构造中。将业务逻辑移动到在所需范围内仅调用一次的方法中,例如 @PostConstruct 注释方法。另见 How and when should I load the model from database for h:dataTable.