Search code examples
jsf-2primefacesfaceletsglassfish-3

Facelet tag parameter not recognized by PrimeFaces p:ajax


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).


Solution

  • 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.