8/06/2011

Using parameterized method calls in JSF 2.0

One of the very nice features of JSF 2.0 is the ability to call action methods with parameters. 


Why is that important ? It is important because it allows you to call any method with a click without having to use parameter tags. This is conjunction with JSF 2.0 composite components lets you do magical things like creating unlimited ICEfaces popups.


Let me explain further:


If you use ICEfaces or JSF in a business environment you will always try to reuse components: Don´t Repeat Yourself (DRY). By using composite components, developers using JSF 2.0 (and ICEfaces 2.0) have this ability: One team is creating the components, another team is reusing them to create great applications.


If you want to create a component that displays an ICEfaces popup (PanelPopup component) you have to find a way to let the user call and recall the same popup. The user must have the possibility to create, close and create the popup again and again. 


So the questions are: 


1) How do you let the business component developer tell the composite component which popup to open ?


2) How has the composite component to be developed to open and close always the right popup and keep its state ?


This is my solution, if you have any other solution, please let me know.


The composite component


The composite component that is rendering the popups is a popup component like you would develop it if you wouldn´t care about reusability. You need a boolean value to determine whether it is opened or not and a close Button. Of course you will always need more buttons, business logic etc etc but for our little example here we will just open and close the popup:



<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
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:icecore="http://www.icefaces.org/icefaces/core"
xmlns:ace="http://www.icefaces.org/icefaces/components"
xmlns:ice="http://www.icesoft.com/icefaces/component">

<head>
    <title>A Popup</title>
</head>
<body>
    <cc:interface>
      <cc:attribute name="bean" required="true" />
    </cc:interface>

    <cc:implementation>
      <ice:panelPopup rendered="#{cc.attrs.bean.show}" modal="true">
      <f:facet name="header">
      <ice:outputText value="Confirmation" />
      </f:facet>
      <f:facet name="body">
      <ice:panelGrid columns="1">
      <ice:outputText value="This is a popup" />
      <ice:commandButton value="Close" actionListener="#{cc.attrs.bean.toggleShow}" />
      </ice:panelGrid>
      </ice:panelGrid>
      </f:facet>
      </ice:panelPopup>
</cc:implementation>
</body>
</html>


As you can see ... nothing special about the composite component so far. We have a bean that holds its state and has a method that allows to toggle the state.


The code


Something much more interesting is the code invoking the composite component:
<composite:popup bean="#{popupCreator.createPopup('test')}" />
We invoke the composite component by calling a parameterized method that returns a Bean. The Bean that we are using in our composite component. This is the code:



private Bean createPopup(String id) {

  Bean bean= beanMap.get(id);
  if (bean== null) {
  bean= new Bean();
  beanMap.put(id, confirmationBean);
  }
  return bean;
}


That´s basically all. If you know how to do composite components, you know how to use this code. This is kind of a generic approach to create truly reusable components. I would be interested in your approaches: How did you solve challenges like this ?




If you like this post it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.