Thursday, August 2, 2012

Calling af:fileDownloadActionListener component programmatically

I had one use case where i need to called af:fileDownloadActionListener programmatically .Let me exaplain the use case first.

Use case: Business user or any user want to download the zip file which contains text's file .But the zip file if going to generated at run time on the basis of the some tough business rule's.It's mean if there is any  failure in business rule then in this case zip file is not going to generated and same time we i need to show the appropriate message to the user.

*If you use af:fileDownloadActionListener directly then if there is no file for download to user so it will  be give error message to user.(this is default feature of the af:fileDownloadActionListener )

So ,if there is some business false in that case i need to skip the file down load listener (to avid to show the error message for example unable to load file  some things like this ).

For over come this use case or problem i have used two command button.let me explain why i used two button and what are they used for ?

1-first button should be visible and it will just call the backing bean method where i have written the business logic for generating the zip file.
(For user prospective he/she thinks this button is  for download but instead-of download task the button is going to call the backing bean.)

2-Second button will going to do actual task and button  have actuall file download listener however it's not going to show on UI.

let me expalin in more details

First command is following which clicking  on the i am calling the a backing bean method

     <af:commandButton text="#{bsnlbillpaymentuiBundle.DOWNLOAD}" id="cb3" disabled="#{!bindings.ExecuteWithParams.enabled}"

In the validationRecords backing bean method i am checking whether do we need to create the zip file or not.And in this method i am checking is the zip file got created or not if not then show the custom pop up with message and if the zip file is present then i am calling the java script where i am queuing the event of the second command button which has the af:filedownloadlistener.

Backing bean method has following code .

        public void validationRecords(ActionEvent actionEvent) {
        ADFContext ctxt = ADFContext.getCurrent();
        SecurityContext sctxt = ctxt.getSecurityContext();
        if (business rule) {
                 FacesContext context = FacesContext.getCurrentInstance();
                ExtendedRenderKitService erks =
                String id =
                erks.addScript(context, "customHandler('" + id + "');");
            } else {
                String msg = "No Records is found ";
                FacesMessage fmsg =
                    new FacesMessage(FacesMessage.FACES_MESSAGES, msg);
                FacesContext context = FacesContext.getCurrentInstance();
                context.addMessage(null, fmsg);

Here in this line  erks.addScript(context, "customHandler('" + id + "');"); 

We are calling java script method which has following code 

 var customHandler= function(event) { var component = AdfPage.PAGE.findComponent(event); var actionEvent = new AdfActionEvent(component); actionEvent.queue(); }

In  java script method i am passing the client id of the second button which i have  already bind to backing bean.Moreover in this method i am also queuing  the event to second button.

And second method has following code which actually has af:fileDownloadlistener component.

     <af:commandButton text="NONE" id="cb1" action=" "
                        disabled="#{!bindings.ExecuteWithParams.enabled}" visible="false"

* This is one way to achieve this type of problem or use case.People might have another way to do.Any suggestion will appreciated.

Prateek Shaw

1 comment:

  1. Hi Prateek

    Can't we just do the below instead of using javascript. I have tried the below it is giving some weird errors and not able to understand why... Is there any reason why you choose java script instead of below code and is anything wrong with this

    public void validationRecords(ActionEvent actionEvent) {
    // Do the validation and it is successful
    // then invoke download
    RichCommandButton button = (RichCommandButton) ADFUtil.findComponentNear(act.getComponent(), "cb1");
    ActionEvent actionEvent = new ActionEvent(button);