<af:setPropertyListener> not working on <af:popup> with childCreation="deferred" !

You should be careful while using <af:setPropertyListener> on <af:popup>. There is a known limitation when you use <af:setPropertyListener> with 'popupFetch' type to initialize the properties/parameters for a <af:popup>. The relevant jsf snippet may look like as shown in the following diagram.

 <af:popup id="p1" contentDelivery="lazyUncached"  
       childCreation="deferred">  
  <af:setPropertyListener from="'check'" to="#{requestScope.params}"  
    type="popupFetch"/>  
  <af:dialog id="d2" title="Check">  
   <af:outputText value="Param from the caller: #{requestScope.params}"  
    id="ot2"/>  
   </af:dialog>  
 </af:popup>    

When you run this page, you may notice that the setPropertyListener with a popupFetch type is not getting called for the first time, and the same works without issues from next time onwards.

What goes wrong here?

Let me try to summarize the reason for this behavior. In the above jsf snippet, <af:setPropertyListener> resides inside the popup body which is not available/processed when the parent page renders for the first time because of the deferred 'child creation' settings (childCreation ="deferred") for the popup. With this deferred configuration popup body is processed when you really ask for it. Please note that, af:setPropertyListener is expected to be evaluated/processed during the Apply Request Values phase in JSF life cycle which may happen much before the Render Response phase. When user opts to view popup, reuest reaches server and JSF lifecycle starts. As there is no popup body at this stage, there is no af:setPropertyListener tag for processing at Apply Request Values phase. Later in the JSF life cycle, popup body is processed at Render Response phase. Apparently next request for showing popup may have fully processed popup body in place, and everything may work as expected at this time.


The work around solution is to use the popupFetchListener method to establish state(pass parameters) instead of <af:setPropertyListener>. If you modify the above jsf snippet as shown below, this use case will work.

 <af:popup id="p2" contentDelivery="lazyUncached"  
       childCreation="deferred"  
       popupFetchListener="#{TestBean.popupFetchAction}">  
  <af:dialog id="d3" title="Check">  
   <af:outputText value="Param from the caller: #{requestScope.params}"  
             id="ot3"/>  
  </af:dialog>  
 </af:popup>  
 public class TestBean {  
  public void popupFetchAction(PopupFetchEvent popupFetchEvent) {  
   ADFContext.getCurrent().getRequestScope().put("params", "check");  
  }  
 }   

Please note that this issue is being tracked as an 'Enhancement Request' by ADF Faces team. Once this is done the above stated limitation is no longer valid.



Learn More ...

There are a lot more points like this. If  you are curious to learn the internals of the ADF Business Components and ADF Binding Layer,  the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post- http://jobinesh.blogspot.in/2012/07/pre-order-your-copy-of-oracle-adf-real.html

Comments

  1. Thanks, great post! I could solve my problem now.

    ReplyDelete

Post a Comment