ICEfaces
  1. ICEfaces
  2. ICE-7381

ace:dataExporter, avoid serving file by hijacking the faces response

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.1-Beta
    • Fix Version/s: 2.1-Beta2, 3.0
    • Component/s: ACE-Components
    • Labels:
      None
    • Environment:
      Any
    • Assignee Priority:
      P2
    • Affects:
      Documentation (User Guide, Ref. Guide, etc.), Sample App./Tutorial

      Description

      The current file delivery mechanism of the dataExporter action, is to hijack the current faces response, by adding it's own headers and including the generated file in the body. This has lead to different issues under certain circumstances. It is necessary to modify the file delivery mechanism for a different, cleaner technique that doesn't interfere with the normal faces response.

        Issue Links

          Activity

          Hide
          Arturo Zambrano added a comment - - edited

          Fixed at revision 26021.

          The data exporter was upgraded to a component, so that it renders itself. The component no longer needs to be inside a UICommand component with <f:ajax disabled="true"/>. The attributes are the same as before, with the addition of 'label', 'singleSubmit', 'style', and 'styleClass'.

          The new approach consists in adding a Resource to the ResoureRegistry and serving it to the client by opening a new window with the URL of this resource, so that it gets loaded in such window and not in the original window.

          Show
          Arturo Zambrano added a comment - - edited Fixed at revision 26021. The data exporter was upgraded to a component, so that it renders itself. The component no longer needs to be inside a UICommand component with <f:ajax disabled="true"/>. The attributes are the same as before, with the addition of 'label', 'singleSubmit', 'style', and 'styleClass'. The new approach consists in adding a Resource to the ResoureRegistry and serving it to the client by opening a new window with the URL of this resource, so that it gets loaded in such window and not in the original window.
          Hide
          Ken Fyten added a comment -

          Having to open a new visible window is a bit archaic for file download. It would be much nicer if we could use a hidden iframe on the page instead, perhaps with a "Please Wait..." type status message while the file is generated.

          Show
          Ken Fyten added a comment - Having to open a new visible window is a bit archaic for file download. It would be much nicer if we could use a hidden iframe on the page instead, perhaps with a "Please Wait..." type status message while the file is generated.
          Hide
          Arturo Zambrano added a comment - - edited

          This issue is now solved, after trying different approaches for different browsers.

          First, in Chrome, and possibly in webkit-based browsers in general, the javax.faces.source request parameter in the POST request had an invalid value when the data exporter button triggered the request. The value should be the client id of the data exporter component, but the client id of the enclosing form was being sent to the server instead. This was fixed by giving more control to the component over ajax requests and preventing the default behavior of the browser. The default behavior in the browser when pressing a <button> element is to submit the form, this was prevented from happening, and an onclick event executed making a call to our own function ice.s to handle the ajax request and send the correct value for the source parameter.

          Another major problem had to do with serving the file in IE7. The initial approach of opening a new window, sending a JSF request, receiving a JSF response with the URL of the generated resource, and finally updating the location of the opened window to that of the dynamic resource for download wasn't working in IE7. The main reason was that since this change in location wasn't triggered by a direct user action but by a dynamic update, the browser always intercepted the file download and showed a pop-up warning message at the top of the window. Then, it was necessary to click on that message and select "download file". The file couldn't be loaded for two reasons. The first reason is that on the server side the actual bytes of the generated file didn't persist. While the Resource object stays in memory for the duration of the session, the input stream associated with it only had a request scope, so when trying for the second time to download the file after the warning message appeared, the bytes of the file weren't available and the downloaded file contained no data. This was fixed by storing the byte array in the Resource object and returning a new input stream as needed. A new issue, linked to this one, was created to optimize this approach to avoid keeping in memory all the bytes of generated files. Even after fixing this problem, the file couldn't be downloaded because IE7 always loaded the original page on the new window, instead of downloading the file after going through the warning message. So, in order to avoid these warning messages, instead of dynamically updating the location of this new window, a link with the location of the resource was rendered in this new window, so that the user could click on it and download the file without any warnings in between.

          Another approach that was tried instead of opening a new window was to load the file through a hidden iframe. This approach worked much better for all other browsers, as it was no longer necessary to open a new window, and the file was downloaded in the same window, without affecting the forms on the page. However, similar problems to those mentioned above were found in IE7, so this approach had to be discarded for this browser and the approach described above was implemented.

          Show
          Arturo Zambrano added a comment - - edited This issue is now solved, after trying different approaches for different browsers. First, in Chrome, and possibly in webkit-based browsers in general, the javax.faces.source request parameter in the POST request had an invalid value when the data exporter button triggered the request. The value should be the client id of the data exporter component, but the client id of the enclosing form was being sent to the server instead. This was fixed by giving more control to the component over ajax requests and preventing the default behavior of the browser. The default behavior in the browser when pressing a <button> element is to submit the form, this was prevented from happening, and an onclick event executed making a call to our own function ice.s to handle the ajax request and send the correct value for the source parameter. Another major problem had to do with serving the file in IE7. The initial approach of opening a new window, sending a JSF request, receiving a JSF response with the URL of the generated resource, and finally updating the location of the opened window to that of the dynamic resource for download wasn't working in IE7. The main reason was that since this change in location wasn't triggered by a direct user action but by a dynamic update, the browser always intercepted the file download and showed a pop-up warning message at the top of the window. Then, it was necessary to click on that message and select "download file". The file couldn't be loaded for two reasons. The first reason is that on the server side the actual bytes of the generated file didn't persist. While the Resource object stays in memory for the duration of the session, the input stream associated with it only had a request scope, so when trying for the second time to download the file after the warning message appeared, the bytes of the file weren't available and the downloaded file contained no data. This was fixed by storing the byte array in the Resource object and returning a new input stream as needed. A new issue, linked to this one, was created to optimize this approach to avoid keeping in memory all the bytes of generated files. Even after fixing this problem, the file couldn't be downloaded because IE7 always loaded the original page on the new window, instead of downloading the file after going through the warning message. So, in order to avoid these warning messages, instead of dynamically updating the location of this new window, a link with the location of the resource was rendered in this new window, so that the user could click on it and download the file without any warnings in between. Another approach that was tried instead of opening a new window was to load the file through a hidden iframe. This approach worked much better for all other browsers, as it was no longer necessary to open a new window, and the file was downloaded in the same window, without affecting the forms on the page. However, similar problems to those mentioned above were found in IE7, so this approach had to be discarded for this browser and the approach described above was implemented.

            People

            • Assignee:
              Arturo Zambrano
              Reporter:
              Arturo Zambrano
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: