Validate Data before Export via af:exportCollectionActionListener or af:fileDownloadActionListener

ADF rich faces offer a nice and easy feature to stream data to the client (e.g. Excel) using the af:exportCollectionActionListener or af:fileDownloadActionListener component. Both of the components get the output stream from the response, so the application an add the data.
One problem is that the two components fire before the application has a chance to validate other data on the page or do some other needed work.
To overcome this shortcoming you can implement the trick I’m outlining in this blog. The idea is to use a normal af:commandbutton or af:commandToolbarButton on the page which calls an actionListener in a bean. In there you can validate other page data or do some other stuff in the model, and then queue an event inside the bean method to call another invisible button on the page which has the af:exportCollectionActionListener attached.

As it turned out (thanks Jiandong Xin for pointing it out), there is a problem if the button we queue the action event to has a client behavior tag attached. This is the case for af:exportCollectionActionListener or af:fileDownloadActionListener. These tags don’t work properly if we only queue an event to the parent button. As Jobinesh pointed out in his blog we need to insert a JavaScript function into the page which handles the event queuing from JavaScript and call it from the bean. This way we are able to set the needed parameters (e.g. not to wait for a response).

Now lets implement this: Lets start with a toolbar button which resides on a panel collection holding the table we want to export. The button has a binding to the bean (binding=”#{exportBean.exportCollectionButton}”) to make it easier to call it from the bean. If you don’t like to bind the button to the bean, you can search for the component by name inside the action listener we implement below. The page contains the custom handler (customHandler(event)) which we call from the bean method. This handler then queues the event to activate the button which starts the file download. The connection between the customHander and hte commandToolbarButton is the ID of the commandToolbarButton (“ctb1”). You have to change this if your button has a different ID.

<af:resource type="javascript">
  function customHandler(event){
    var exportCmd = AdfPage.PAGE.findComponentByAbsoluteId("ctb1");
    var actionEvent = new AdfActionEvent(exportCmd);
<af:panelCollection id="pc1">
  <f:facet name="menus"/>
    <f:facet name="toolbar">
      <af:toolbar id="t2" binding="#{exportBean.toolbar}">
        <af:commandToolbarButton text="Export..." id="ctb1"
          <af:exportCollectionActionListener type="excelHTML" exportedId="t1"

The vital part is that the visible property is set to “false”, so that the button will not show up on the page, but is fully functional. Somewhere else on the page (or even on the same toolbar) we have an with an action listener pointing to a bean method (exportBean in the sample). This button is visible and used to initiate the export.

<af:commandButton text="export via bean" id="cb8" 

The exportBean actionListener looks like this

    // toolbar button with export listner attatch bound from page
    private RichCommandToolbarButton exportCollectionButton;
    public void exportprgActionListener(ActionEvent actionEvent) {
        // Add event code (validation or other) here...

        // queue the event via a JavaScript inserted into the page
        FacesContext context = FacesContext.getCurrentInstance();
        ExtendedRenderKitService erks =
        Service.getService(context.getRenderKit(), ExtendedRenderKitService.class);
        erks.addScript(context, "customHandler();");

In the action listener above you can validate other data on the page or call service methods in your application module before starting the export, or cancel the export if you like. The export runs as if you click the af:exportCollectionActionListener directly.
You can download a sample workspace
After download remove the ‘.doc’ suffix!

8 thoughts on “Validate Data before Export via af:exportCollectionActionListener or af:fileDownloadActionListener

    • Yes, I reviewed the issue. t turned out, that indeed the button event is queued, but one need to handle the event in a special way if a client behavior tag is used together with the button. This is the case for af:exportCollectionActionListener or af:fileDownloadActionListener. Jobinesh thankfully has the solution bloged and I changed my sample according to it.
      Still I’m looking for a solution to do it without JavaScript.

      Thanks for pointing this out.

  1. Pingback: Export to Excel enhancements in JDeveloper and JDeveloper 12.1.3 | JDev & ADF Goodies

  2. Hello Timo,

    now I know that this is an old post, but some solutions are timeless🙂

    before I read this post, I used to have a hidden button with an af:fileDownloadActionListener and another one visible that queues the event of the hidden button (jdev 12.1.3).
    The way to queue the event was like the one below and not through java script.

    ActionEvent actEvnt = new ActionEvent(printButton);

    In this way though I’m getting the below error.
    What’s the difference with queueing the event through javascript??

    Servlet execution in servlet context “ServletContext@707961851[app:xxxxx module:xxxxx path:null spec-version:3.0 version:10.01.028]” failed, Didn’t meet stated Content-Length, wrote: ‘0’ bytes instead of stated: ‘-1’ bytes.. Didn’t meet stated Content-Length, wrote: ‘0’ bytes instead of stated: ‘-1’ bytes. at weblogic.servlet.internal.ServletOutputStreamImpl.ensureContentLength( at weblogic.servlet.internal.ServletResponseImpl.ensureContentLength( at weblogic.servlet.internal.ServletResponseImpl.send( at at weblogic.servlet.provider.ContainerSupportProviderImpl$ at at

    Thanks a lot

    • What comes to mind is the time the event is actually executed. For me it looks like the event if queued in the bean is executed to early. If you add it into the page via JavaScript it gets executed late enough that all other initialization are done.
      This is not verified but only my hunch on this.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s