Facelet tag parameter not recognized by PrimeFaces p:ajax
Asked Answered
S

2

8

I have a simple Facelet tag:

<ui:composition>
  <ui:insert />
</ui:composition>

which is used in order to avoid declaring multiple c:set tags.
Let's say I registered it in the facelets taglib library with the name view, and use it like this:

<my:view bean="#{myController}">
  <p:inputText value="#{bean.value}>
    <p:ajax event="blur" process="@this" listener="#{bean.handleValueChanged}" />
  </p:inputText>
</my:view>

The attribute value is perfectly resolved by p:inputText, but p:ajax throws this:

Target Unreachable, identifier 'bean' resolved to null
javax.el.PropertyNotFoundException: Target Unreachable, identifier 'bean' resolved to null
    at com.sun.el.parser.AstValue.getTarget(AstValue.java:153)
    at com.sun.el.parser.AstValue.invoke(AstValue.java:237)
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:302)
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:39)
    at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
    at org.primefaces.component.behavior.ajax.AjaxBehaviorListenerImpl.processAjaxBehavior(AjaxBehaviorListenerImpl.java:47)

Is it a bug or expected behavior?

Update: I just tried the same with f:ajax and it worked!

Btw, the environment is as follows:
Glassfish 3.1.2
PF 3.0, 3.2, 3.3

Update2:
This issue with RichFaces is absolutely identical. Seems to be like a PrimeFaces bug (I'll post an issue on PF bug tracker today).

Sheridan answered 21/5, 2012 at 19:49 Comment(1)
As promised, I opened the issue on PF bug tracker: code.google.com/p/primefaces/issues/detail?id=4075Sheridan
S
4

My colleague has just provided a patch to resolve this issue.

The current implementation of AjaxBehaviorListenerImpl#processAjaxBehaviour is as follows:

public void processAjaxBehavior(AjaxBehaviorEvent event) throws AbortProcessingException {
        FacesContext context = FacesContext.getCurrentInstance();
        final ELContext elContext = context.getELContext();

        try{
            listener.invoke(elContext, new Object[]{});
        } catch (MethodNotFoundException mnfe) {
            MethodExpression argListener = context.getApplication().getExpressionFactory().
                        createMethodExpression(elContext, listener.getExpressionString(), null, new Class[]{event.getClass()});

            argListener.invoke(elContext, new Object[]{event});
        }
    }

He proposes to tweak it like this:

import javax.faces.view.facelets.FaceletContext;

public void processAjaxBehavior(AjaxBehaviorEvent event) throws AbortProcessingException {
        FacesContext context = FacesContext.getCurrentInstance();
        final ELContext elContext = context.getELContext();

        try{
            listener.invoke(elContext, new Object[]{});
        } catch (MethodNotFoundException mnfe) {
            FaceletContext fc = (FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
            MethodExpression argListener = context.getApplication().getExpressionFactory().
                        createMethodExpression(fc, listener.getExpressionString(), null, new Class[]{ event.getClass() });

            argListener.invoke(elContext, new Object[]{ event });
        }
    }

Hopefully this will be approved by PF team.

Sheridan answered 23/5, 2012 at 10:48 Comment(4)
Nice job! This can theoretically solve a problem which we have when using <p:ajax event="rowEdit"> in a tag file.Daryl
@Daryl Thanks! Though, all kudos should go to my colleague (I doubt if he has SO account). I just noticed the problem, and he solved it :) Is there an open bug regarding <p:ajax event="rowEdit/> or a question on SO? Just curious, because I haven't come across this issue, so I want to take a look.Sheridan
No, it's for my job. We've a tag file which contains a <p:column><p:rowEditor> along with a <p:ajax event="rowEdit" listener="#{bean.save}"> so that it can be included as a single tag by <my:rowEditorColumn> in data table. However the <p:ajax> did never invoke the listener method.Daryl
How can this fix the problem since the original exception is a PropertyNotFoundException and not a MethodNotFoundException?Cryo
S
-1

The tweak does not work with my use case which is more complex than a single ui:include.

<c:forEach items="#{items}" var="item">
            <ui:include src="#{item.uri}">
                <ui:param name="itemBean" value="#{item.bean}"/>
            </ui:include>

</c:forEach>

I think the listener's variable mapper must be reused inside the new MethodExpression

Scooter answered 26/6, 2012 at 6:54 Comment(4)
mention it in comments or ask another question please. SO is not a forum.Edra
I just cannot, not enough reputation and asking a new question is not a solution. By the way, I have submit a patch to this issue code.google.com/p/primefaces/issues/detail?id=4075 (as nithril) which was accepted and appliedScooter
sorry about the reputation limit. This problem still exists in current 3.5 did your problems disappear after this fix?Edra
The problem dissapear as soon as the action method takes an argument of AjaxBehaviorEvent type instead of the PF event. It is complex to fix completely the issue so I think it is an acceptable workaroundScooter

© 2022 - 2024 — McMap. All rights reserved.