Tuesday 12 January 2016

Lambda expression as JSF actionListener

Introduction

Although there is no official version of JSF which supports Java 8, there are various application servers that run on it today. And thus can we use some Java 8 features today.

I'll show you in this blog post an example of using a lambda expression as an action listener. And more specific where we have a custom composite component with multiple actions sources.

And although I'm not a fan of the binding property, probably due to the issues I had with it during the early days of JSF 1.x, it is a nice use case for Lambda expressions.

Custom composite component

Short recap of what a custom composite component is.
If you have on multiple screens a set of components used in the same manner, you can create a custom component for it. The markup doesn't need to be exactly the same on all those pages or linked to the same managed bean, because you can specify parameters.

That way you can also 'build' your screens using different reusable blocks and you have a very modular approach comparable with using Java methods to increase readability.

And creating those custom composite components is very easy in JSF 2.x. Create JSF file with the definition of your component (interface  and implementation parts) in a special specific folder and you are ready to use it due to the convention principles in place.
Have a search on the internet on this topic and you find various examples how you can do it.

Assigning an action listener to a button within your custom composite components seems for some people a bit more difficult but using the actionSource attribute of the composite component namespace makes it very easy.

<ui:component xmlns="http://www.w3.org/1999/xhtml"
              xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
              xmlns:cc="http://xmlns.jcp.org/jsf/composite"
              xmlns:p="http://primefaces.org/ui">

    <cc:interface>
        <cc:actionSource name="submitListener" targets="submitBtn"/>
        <cc:actionSource name="cancelListener" targets="cancelBtn"/>
    </cc:interface>
    <cc:implementation>
        <div>
            Some multiple button component 
            <p:commandButton id="submitBtn" value="Submit"/>
            <p:commandButton id="cancelBtn" value="Cancel" immediate="true"/>
        </div>
    </cc:implementation>
</ui:component>


The above example defines a custom composite component where we have 2 buttons and each of them, we can assign a different actionListener.

ActionListener

ActionListener is a JSF interface defined for those implementations which want to respond on the click on a button (for example there are other components which also generate the same event) on the screen.

The interface has just one method, as you can see;
/**
 * Invoked when an action occurs.
 * @param e the event to be processed
 */
public void actionPerformed(ActionEvent e);

This makes it an ideal candidate to use it in combination with Lambda expressions since we have a functional interface.

So the following lambda expression
e -> System.out.println("Save clicked");

is valid implementation for the actionListener interface and thus we can assign such methods to the button(s).

Binding the actionListener implementation

As a said in the introduction, with the binding attribute, it is very easy to 'bind' an implementation of the ActionListener interface to the button. 

<adv:multiple>
    <f:actionListener for="submitListener" binding="#{cityBean.save}"/>
    <f:actionListener for="cancelListener" binding="#{cityBean.cancel}"/>
</adv:multiple>
In the above example we retrieve the instance to which the listener is bound to, with a method result. The java code can be as follows.

@Modelpublic class CityBean {

   private ActionListener save;
   private ActionListener cancel;

   @PostConstruct
   public void init() {
      save = e -> System.out.println("Save clicked");
      cancel = e -> System.out.println("Cancel clicked");
   }

   public void performSearch() {
      System.out.println("Searching ");
   }

   public ActionListener getSave() {
      return save;
   }

   public ActionListener getCancel() {
      return cancel;
   }

}
As you can see, this is a nice,clean usage of lambda expressions where we have multiple actionListener targets in the custom composite component.

Conclusion

Using a lambda expression for an ActionListener implementation make your code much more readable and reduces the boilerplate in those cases where you need multiple actionSources for a custom composite component.

Enjoy Java 8 and Java EE!