Question

I'm trying to refresh a jsf component using java code. First, i try using this :

FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add("MyCompId");

but it produce an "UnsupportedOperationException". Then, i try to install omnifaces and use Ajax.update("MyComp"). The result is the same :

org.apache.myfaces.view.facelets.el.ContextAwareELException: javax.el.ELException: java.lang.UnsupportedOperationException
    at org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression.invoke(ContextAwareTagMethodExpression.java:108)
    at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:68)
    at javax.faces.component.UICommand.broadcast(UICommand.java:120)
    at javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:1041)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:289)
    at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1415)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:765)
    at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:38)
    at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:170)
    at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:197)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:357)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._doFilterImpl(TrinidadFilterImpl.java:303)
    at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:208)
    at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)
Caused by: javax.el.ELException: java.lang.UnsupportedOperationException
    at org.apache.el.parser.AstValue.invoke(AstValue.java:291)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:274)
    at org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression.invoke(ContextAwareTagMethodExpression.java:96)
    ... 34 more
Caused by: java.lang.UnsupportedOperationException
    at java.util.AbstractCollection.add(AbstractCollection.java:221)
    at org.omnifaces.util.Ajax.update(Ajax.java:75)

I try to reproduce the same example found here : http://showcase.omnifaces.org/utils/Ajax. My XHTML :

<!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"
    xmlns:c="http://java.sun.com/jsp/jstl/core">
<f:view  contentType="text/html">
    <h:body id="body">
        <h:form id="form">
            <div id="contentStyle">    
                <h:panelGroup styleClass="blocLsMsgErr" id="messages">
                    <h:panelGroup styleClass="lsMsgErr">
                        <h:dataTable var="facesMessage"
                            value="#{messagesComponent.listeCustomFacesMessage1}">
                            <h:column>
                                <h:graphicImage alt="icon"
                                    value="/images/messages/#{facesMessage.severity}_icon.png" />
                            </h:column>
                            <h:column>
                                <h:outputLink rendered="#{not empty facesMessage.id}"
                                    styleClass="titre #{facesMessage.severity}"
                                    onclick="document.getElementById('#{facesMessage.id}').focus();return false;">
                                    <h:outputText value="#{facesMessage.summary} " />
                                </h:outputLink>
                                <h:outputText rendered="#{empty facesMessage.id}"
                                    styleClass="titre #{facesMessage.severity}"
                                    value="#{facesMessage.summary} " />
                            </h:column>
                            <h:column>
                                <h:outputText styleClass="#{facesMessage.severity}"
                                    value=" -1- " />
                            </h:column>
                            <h:column>
                                <h:outputText styleClass="#{facesMessage.severity}"
                                    value="#{facesMessage.detail}" />
                            </h:column>
                        </h:dataTable>

                        <h:panelGrid columns="1">
                            <ui:repeat value="#{messagesComponent.listeCustomFacesMessage2}"
                                var="facesMessage">
                                <h:graphicImage alt="icon"
                                    value="/images/messages/#{facesMessage.severity}_icon.png" />
                                <h:outputLink rendered="#{not empty facesMessage.id}"
                                    styleClass="titre #{facesMessage.severity}"
                                    onclick="document.getElementById('#{facesMessage.id}').focus();return false;">
                                    <h:outputText value="#{facesMessage.summary} " />
                                </h:outputLink>
                                <h:outputText rendered="#{empty facesMessage.id}"
                                    styleClass="titre #{facesMessage.severity}"
                                    value="#{facesMessage.summary} " />
                                <h:outputText styleClass="#{facesMessage.severity}"
                                    value=" -2- " />
                                <h:outputText styleClass="#{facesMessage.severity}"
                                    value="#{facesMessage.detail}" />
                                <br />
                            </ui:repeat>
                        </h:panelGrid>

                        <h:panelGrid columns="4">
                            <c:forEach items="#{messagesComponent.listeCustomFacesMessage3}"
                                var="facesMessage">
                                <h:graphicImage alt="icon"
                                    value="/images/messages/#{facesMessage.severity}_icon.png" />
                                <h:outputLink rendered="#{not empty facesMessage.id}"
                                    styleClass="titre #{facesMessage.severity}"
                                    onclick="document.getElementById('#{facesMessage.id}').focus();return false;">
                                    <h:outputText value="#{facesMessage.summary} " />
                                </h:outputLink>
                                <h:outputText rendered="#{empty facesMessage.id}"
                                    styleClass="titre #{facesMessage.severity}"
                                    value="#{facesMessage.summary} " />
                                <h:outputText styleClass="#{facesMessage.severity}"
                                    value=" -3- " />
                                <h:panelGroup>
                                    <h:outputText styleClass="#{facesMessage.severity}"
                                        value="#{facesMessage.detail}" />
                                    <br />
                                </h:panelGroup>
                            </c:forEach>
                        </h:panelGrid>

                    </h:panelGroup>
                </h:panelGroup>

                <ui:insert name="content" />

                <h:commandButton styleClass="button"
                    value="#{messages.boutonSuivant}" id="buttonNext"
                    action="#{testBean.nextPage}">
                    <f:ajax />
                </h:commandButton>
            </div>
            <h:commandButton value="submit" action="#{testBean.update}">
                <f:ajax />
            </h:commandButton>
        </h:form>
    </h:body>
</f:view>
</html>

My Bean :

import javax.inject.Named;

import org.omnifaces.util.Ajax;
import org.springframework.context.annotation.Scope;

@Named
@Scope("session")
public class TestBean {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public void update() {
        System.out.println("Ajax update");
        Ajax.update("messages");
        System.out.println("Ajax update OK");
    }

    public String nextPage() {

        if (!this.validationChampsPagePersonne()) {
            return null;

        }

        return "next";
    }

    private boolean validationChampsPagePersonne() {
    //doing a FacesContext.getCurrentInstance().addMessage(null, facesMessage);
    }

}

Other informations : I'm using myfaces api and implementation (version 2.1.11), trinidad 2.1.0, tomahawk2 1.1.14, primefaces 3.5

Any idea?

Thanks

Était-ce utile?

La solution

MyFaces can't be the cause, it has always worked in MyFaces for us and anyone else. We have however never really used Trinidad, so I took a look in the Trinidad source code. It appears that it returns Collections#emptySet() when there are no render IDs. This is however immutable! This totally explains the exception you're facing.

This is a rather astonishing bug in Trinidad. The javadoc clearly says that the returned collection must be mutable.

Return a Collection of client identifiers from the current request with the request parameter name PARTIAL_RENDER_PARAM_NAME. If there is no such request parameter, return an empty Collection. These client identifiers are used to identify components that will be processed during the render phase of the request processing lifecycle. The returned Collection is mutable.

If you like Trinidad, report it as a bug to the Trinidad guys. Otherwise just get rid of it. I don't see any reason to use it if you're already using PrimeFaces (and Tomahawk).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top