Why am I able to bind <f:actionListener> to an arbitrary method if it's not supported by JSF?

你离开我真会死。 提交于 2019-12-01 04:45:54

问题


I'm using Glassfish 3.1.2.2 and JSF Mojarra 2.1.6.

I have the following Facelets page:

<h:form>
  <h:commandLink value="link">
    <f:actionListener binding="#{backingBean.someMethod(1)}"/>
  </h:commandLink>
</h:form>

And the following backing-bean:

@RequestScoped
@ManagedBean
public class BackingBean {
  public void someMethod(int i) {
    System.out.println("It was called: " + i);
  }
}

When I click the link, "Info: It was called: 1" appears in the console.

The documentation for binding reads:

Library: http://xmlns.jcp.org/jsf/core, http://java.sun.com/jsf/core (Jsf Core)

Tag: actionListener

binding

Value binding expression that evaluates to an object that implements javax.faces.event.ActionListener. [emphasis mine]

Also, the accepted answer to this question states that it's not possible for an f:actionListener to call an arbitrary method.

Why is the backing bean method called if this isn't supported?


回答1:


This is the consequence of the new EL 2.2 feature of calling a method in a value expression via the #{bean.method()} syntax instead of only referencing a property via the #{bean.property} syntax (which should indeed be of the exact type ActionListener). It wouldn't have worked in EL 2.1 or older and it would also not work when you remove the arguments and the parentheses. That document was written when EL 2.2 didn't exist (it's actually not modified as compared to JSF 1.2 version from May 2006; EL 2.2 was introduced December 2009). I however do agree that it needs an update on that part as it's confusing to starters.

The answer you found made its points based on the document, but the answerer however didn't seem to realize based on the question that while binding="#{testController.nodeListener}" failed, the binding="#{testController.nodeListener(event)}" actually worked. This only doesn't give you the opportunity to pass the ActionEvent. The answer was better if it suggested to just use binding="#{testController.nodeListener()}" instead and grab the event information in other way, such as by calling UIComponent#getCurrentComponent() or even by passing #{component} as argument. Only if you really need to have a hand of it, of course.

<h:commandLink value="link">
    <f:actionListener binding="#{bean.someMethod(component)}"/>
</h:commandLink>
public void someMethod(UIComponent component) {
    System.out.println("It was called on: " + component); // HtmlCommandLink
}

See also:

  • Invoke direct methods or methods with arguments / variables / parameters in EL
  • Difference between JSP EL, JSF EL and Unified EL
  • Differences between action and actionListener


来源:https://stackoverflow.com/questions/30744949/why-am-i-able-to-bind-factionlistener-to-an-arbitrary-method-if-its-not-supp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!