14 Replies Latest reply: Mar 23, 2012 1:29 AM by Lu Han RSS

a4j:ajax "listener" not evaluating/invoking MethodExpression properly?

Kip Moore Newbie

I'm in the process of upgrading my application from Facelets/JSF 1.2/RichFaces 3.3.3 to JSF 2.0/RichFaces 4.0 and I'm having trouble transitioning from the a4j:support tag to the a4j:ajax tag.  Specifically, I'm having difficulty using a ui:param to pass a MethodExpression to the "listener" property of the a4j:ajax tag.  This is a technique that was working for for me with the old a4j:support tag, and my application uses this pattern extensively, so I'm really keen to find a solution!

 

Here's a simplified example of what I'm trying to do with the a4j:ajax tag which is *not* working right now.

 

 

test_outer.xhtml

 

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:a4j="http://richfaces.org/a4j"
      xmlns:rich="http://richfaces.org/rich">

    <ui:composition>

        <html>

            <h:head>
            </h:head>

            <h:body>

                <h:form>
                        <ui:include src="test_inner.xhtml">
                            <ui:param name="controller_bean" value="#{TestBean}"/>
                        </ui:include>                    
                </h:form>

            </h:body>

        </html>
    </ui:composition>
</html>

 

 

test_inner.xhtml

 

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:a4j="http://richfaces.org/a4j"
      xmlns:rich="http://richfaces.org/rich">

    <ui:composition>

            <rich:extendedDataTable    value = "#{controller_bean.list}"
                                    var = "rowvar"
                                    selectionMode="single">

                <a4j:ajax event="selectionchange" listener="#{controller_bean.action}"/>

                <rich:column>  
                    <f:facet name="header">
                        <h:outputText value="Value" />
                    </f:facet>
                    <h:outputText value="#{rowvar}"/>   
                </rich:column>

            </rich:extendedDataTable>        

    </ui:composition>
</html>

 

 

TestBean.java

 

@ManagedBean(name="TestBean")
@SessionScoped
public class TestBean
{
    private static Logger     logger                     = Logger.getLogger(TestBean.class.getName());

    public List<String> getList()
    {
        String[] num = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
        ArrayList<String> nums = new ArrayList<String>(Arrays.asList(num));
        return nums;
    }

    public void action(AjaxBehaviorEvent event)
    {
        logger.info("action");
    }

}

 

With this code, when I select a row in the extendedDataTable, I get an error:

WARNING [javax.enterprise.resource.webcontainer.jsf.lifecycle] Target Unreachable, identifier 'controller_bean' resolved to null: javax.el.PropertyNotFoundException: Target Unreachable, identifier 'controller_bean' resolved to null
...
ERROR [STDERR] javax.faces.FacesException: Target Unreachable, identifier 'controller_bean' resolved to null
...
ERROR [STDERR] Caused by: javax.el.PropertyNotFoundException: Target Unreachable, identifier 'controller_bean' resolved to null

This error seems transparently bogus to me, because the table otherwise displays the values in the list.

 

 

What I had been doing (which was working great until now) was use the a4j:support tag:

 

<a4j:support event="onselectionchange" actionListener="#{controller_bean.action}"/>

 

In this case, the action method (with the proper ActionEvent signature, of course) would get invoked, no problem.

 

Help!

  • 1. a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Nick Belaevski Master

    Hi Kip,

     

    I think it's more to updated Facelets than to RichFaces. What if you add #{controller_bean} anywhere inside included template, do you see output for your bean?

  • 2. Re: a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Kip Moore Newbie

    If I'm understanding your question correctly, yes, I do.  The list of items I am using to populate the extendedDataTable comes from #{controller_bean.list} and that list displays fine in the table, so the "controller_bean" ui:param seems to be getting passed to test_inner.xhtml just fine.

     

    I've been doing some more experimenting as well, and if I add:

     

    <h:commandButton value="Test Button" actionListener="#{controller_bean.actionListener}"/>
    

     

    to test_inner.xhtml, that properly invokes an actionListener method in TestBean.java, as would be expected.  So I think my configuration/setup is fine; this seems to be specifically related to a4j:ajax not liking what Facelets (or me) is passing to the "listener" attribute.  I just don't see what I am doing wrong, especially if on the same page I am successfully passing a MethodExpression via a ui:param to an Ajax actionListener attribute of a different component.

     

    In other words, I don't understand why this seems to be working just fine for a common Ajax actionListener attribute, but not the "listener" attribute of a4j:ajax.  Both of these attributes are supposed to accept MethodExpressions, aren't they?  I just can't figure out why the Facelets method expression is working in one place and not the other.

  • 3. a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Nick Belaevski Master

    Kip,

     

    Ok, we need to investigate. Someone will get back to you soon.

  • 4. Re: a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Kip Moore Newbie

    Thanks for looking into this, Nick, I really appreciate it!

     

    I have tweaked my example a bit to test for proper MethodExpression and ValueExpression evaluation on the same page, I just wanted to post it for completeness' sake.

     

     

    test_inner.xhtml

     

    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:h="http://java.sun.com/jsf/html" 
          xmlns:a4j="http://richfaces.org/a4j"
          xmlns:rich="http://richfaces.org/rich">
    
        <ui:composition>
    
                <rich:extendedDataTable    value = "#{controller_bean.list}"
                                        var = "rowvar"
                                        selectionMode="single">
    
                    <a4j:ajax event="selectionchange" listener="#{controller_bean.listener}"/>
    
                    <rich:column>  
                        <f:facet name="header">
                            <h:outputText value="Value" />
                        </f:facet>
                        <h:outputText value="#{rowvar}"/>   
                    </rich:column>
    
                </rich:extendedDataTable>        
    
                  <h:commandButton value="Test" actionListener="#{controller_bean.actionListener}"/>
    
        </ui:composition>
    </html>
    

     

     

    TestBean.java

     

    @ManagedBean(name="TestBean")
    @SessionScoped
    public class TestBean
    {
        private static Logger     logger                     = Logger.getLogger(TestBean.class.getName());
    
        public List<String> getList()
        {
            String[] num = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
            ArrayList<String> nums = new ArrayList<String>(Arrays.asList(num));
            return nums;
        }
    
        public void listener(AjaxBehaviorEvent event)
        {
            logger.info("listener");
        }
    
        public void actionListener(ActionEvent event)
        {
            logger.info("actionListener");
        }
    }
    

     

     

    If I change

     

    <a4j:ajax event="selectionchange" listener="#{controller_bean.listener}"/>

     

    to

     

    <a4j:ajax event="selectionchange" listener="#{TestBean.listener}"/>

     

    on test_inner.xhtml, then the listener method will get invoked properly.  ValueExpressions seem to be getting properly invoked in other components, as do MethodExpressions; however the MethodExpression invocation on the "listener" attribute of a4j:ajax will only get invoked if the backing bean is referenced directly.

  • 5. Re: a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Kip Moore Newbie

    So I'm still troubleshooting this, and I came across some information that indicated to me that a4j:ajax is an extension of f:ajax, so I decided to try using f:ajax instead and see if I got any different results.  I added the following to my test_inner.xhtml page:

     

    <h:commandButton value="Action Listener" actionListener="#{controller_bean.actionListener}"/>
    <h:commandButton value="f:ajax listener w/direct bean reference">
         <f:ajax event="click" listener="#{TestBean.listener}"/>
    </h:commandButton>
    <h:commandButton value="f:ajax listener w/ui:param">
         <f:ajax event="click" listener="#{controller_bean.listener}"/>
    </h:commandButton>
    <h:commandButton value="a4j:ajax listener w/direct bean reference">
         <a4j:ajax event="click" listener="#{TestBean.listener}"/>
    </h:commandButton>
    <h:commandButton value="a4j:ajax listener w/ui:param">
         <a4j:ajax event="click" listener="#{controller_bean.listener}"/>
    </h:commandButton>
    

     

    Interestingly, the only *broken* interaction is with the 5th and last h:commandButton, the one that uses:

     

    <a4j:ajax event="click" listener="#{controller_bean.listener}"/>

     

    This causes an exception identical to the one I outlined previously in the thread.  All of the other buttons call the backing method as would be expected, which is good news!  Furthermore, replacing a4j:ajax with f:ajax in my rich:extendedDataTable gives me back the main functionality that I need right now.

     

    For me, using f:ajax is likely a good short-term solution, even though it is a step backwards in terms of functionality relative to a4j:ajax.  (Specifically, I would like to use the "status" attribute of a4j:ajax, but not having that available to me right now is not a show-stopper, fortunately.) Over the long term I would want a4j:ajax to behave like f:ajax, but I can live with it for now.

     

    At this point I'm inclined to make the assumption that this is a bug in a4j:ajax - should I file a bug report?

  • 6. Re: a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Nick Belaevski Master

    Hi Kip,

     

    Sure, please post JIRA issue.

  • 8. a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Nick Belaevski Master

    Thanks, will take a look now!

  • 9. a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Nick Belaevski Master

    Just committed the fix - will be available in 4.0.0.Final.

  • 10. Re: a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Jerome Albin Newbie

    Hi Nick,

     

    I've just encountered exactly the same problem as Kip despite the fact that I'm using RichFaces 4.0.0.Final.

    The only difference is that I'm using a h:selectBooleanCheckbox instead of h:commandButton.

    Is it possible that the fix was finally not included in 4.0.0.Final or maybe the fix only applies to h:commandButton and does not work in the context of a checkbox ?

     

    For the short term, I also used f:ajax.

     

    Thanks,

    Jérôme

  • 11. Re: a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Lu Han Newbie

    I encountered the very same issue in RF4.1.0.Final, and the only way to quick fix is change the a4j:ajax to f:ajax.

    I think it's not related with the special component, if the MBean is used directly instead of use ui:param to wrap, it works.

     

    So, please check it and I hope you could fix it in the next version.

  • 12. Re: a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Lu Han Newbie

    Hi Nick,

    What's up about this issue? Would you please provide more information about it?

     

    I like to give a simple sample for that:

     

    outside file:

    <!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:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"

    xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich">

    <h:head></h:head>

     

    <h:body>

              <h:form id="outsideForm">

                        <rich:panel id="outsidePanel" style="border:none">

                                  <ui:include src="include.xhtml">

                                            <ui:param name="mBean" value="#{testList}" />

                                  </ui:include>

                        </rich:panel>

              </h:form>

    </h:body>

    </html>

     

    include file:

    <ui:composition xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"

              xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich">

              <h:panelGrid>

                        <rich:select value="#{mBean.selected}" defaultLabel="choose one ...">

                                  <f:ajax event="selectitem" listener="#{mBean.print}" render="out1" />

                                  <f:selectItems value="#{mBean.item}" var="number" itemValue="#{number}" itemLabel="#{number}" />

                        </rich:select>

                        <h:outputText id="out1" value="selected= #{mBean.selected}" />

              </h:panelGrid>

     

              <h:panelGrid>

                        <rich:select value="#{mBean.selected}" defaultLabel="choose one ...">

                                  <a4j:ajax event="selectitem" listener="#{mBean.print}" render="out2" />

                                  <f:selectItems value="#{mBean.item}" var="number" itemValue="#{number}" itemLabel="#{number}" />

                        </rich:select>

                        <h:outputText id="out2" value="selected= #{mBean.selected}" />

              </h:panelGrid>

     

              <a4j:log level="error"/>

    </ui:composition>

     

    The second one cannot work and throw the errors:

     

    error[11:46:06.592]: Received 'error@serverError' event from <div id=outsideForm:j_idt15 class="rf-sel" ...>

     

    error[11:46:06.594]: [200] class javax.el.PropertyNotFoundException: Target Unreachable, identifier 'mBean' resolved to null

     

    My richfaces is 4.1.0.Final

    ...

    <rf.version>4.1.0.Final</rf.version>

    </properties>

    <dependencies>

      <dependency>

                                  <groupId>org.richfaces.ui</groupId>

                                  <artifactId>richfaces-components-ui</artifactId>

                                  <version>${rf.version}</version>

                        </dependency>

                        <dependency>

                                  <groupId>org.richfaces.core</groupId>

                                  <artifactId>richfaces-core-impl</artifactId>

                                  <version>${rf.version}</version>

                        </dependency>

    ...

  • 13. Re: a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Lukáš Fryč Master

    Hi Lu Han,

     

    could you please add the sample you provided here to the comments of

    https://issues.jboss.org/browse/RF-11469?

     

    I assume it's the same issue.

  • 14. Re: a4j:ajax "listener" not evaluating/invoking MethodExpression properly?
    Lu Han Newbie

    Hi Lukas,

    Thank you for your reply, I think it's the same issue! And, I wish all ajax mode of the component should work well on rf4.3.

    BTW, would you please talk about the time of releasing 4.2.x and 4.3.x, that's very important for us. And if there is a thread said that, please tell me, kindly.

     

    Thanks,

    Lu Han