Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0-Beta2
    • Fix Version/s: 2.0.0
    • Component/s: ACE-Components
    • Labels:
      None
    • Environment:
      ACE
    • Affects:
      Documentation (User Guide, Ref. Guide, etc.)

      Description

      When files are being uploaded, the FileEntryPhaseListener should register a dynamic resource, which will be a simple text file that describes the progress as a JSON data structure. The resource should have all the proper HTTP headers for not being cached. The uploading code will poll the progress at some configurable interval, defaulted to every 2 seconds. A client-side progress bar will show the progress per file, and for the upload as a whole. When the DOM update comes, we may have to adjust the FileEntryRenderer to include the progress bars, otherwise they may be stomped over and lost.

        Activity

        Hide
        Mark Collette added a comment -

        Older browsers, such as IE6, allow only two socket connections to the server. So, if one socket is currently being used to upload the file, then only one remains for other interactions. If server push is being used, then that would involve the second socket being used for a blocking connection, leaving none for obtaining progress information. As such, progress should be implemented via server push, instead of on it's own.

        The basic building blocks of the solution are as follows:

        1. Server side preparation before upload

        On the server side, a resource for the progress information will be registered in either request or session scope. As well, a push id will be created. When the fileEntry component renders itself, it will send the URL of the resource and the push id to the browser.

        2. Client side work immediately before submit / upload

        The fileEntry javascript will register the push id with the bridge, giving a function callback, which will respond to progress push notifications.

        3. Server side work during upload, for progress notification

        When there is sufficient progress, and some amount of time has passed since the last progress notification, the resource contents will be updated with the new progress information, and a push notification will be given.

        4. Client side work during upload, in progress notifications

        When there is progress, the javascript progress function will use the XMLHttpRequest to access the resource. The resource may contain a JSON data structure with the progress information for all of the files, as well as the total progress, if possible. Potentially the success/failure messages will be included as well. The user interface will be updated with this data.

        There will be a race condition, if the resource is in request scope, where the request will have finished, and the response will be transmitted to the browser, and in-between the browser may respond to push notifications, where the resource is no longer available. The client code should gracefully accept this, and do nothing.

        5. Server side work after upload

        When rendering the fileEntry component after the uploads have completed, it should render the same UI that the progresses rendered, but with everything completed. And the registered resource should be set to depict everything as completed as well.

        6. Client side work after upload

        When the component javascript gets the iframe updates after the upload, it should de-register itself from push notifications, so that the bridge may cease maintaining a blocking connection, if the fileEntry upload operation was the sole use of it.

        Show
        Mark Collette added a comment - Older browsers, such as IE6, allow only two socket connections to the server. So, if one socket is currently being used to upload the file, then only one remains for other interactions. If server push is being used, then that would involve the second socket being used for a blocking connection, leaving none for obtaining progress information. As such, progress should be implemented via server push, instead of on it's own. The basic building blocks of the solution are as follows: 1. Server side preparation before upload On the server side, a resource for the progress information will be registered in either request or session scope. As well, a push id will be created. When the fileEntry component renders itself, it will send the URL of the resource and the push id to the browser. 2. Client side work immediately before submit / upload The fileEntry javascript will register the push id with the bridge, giving a function callback, which will respond to progress push notifications. 3. Server side work during upload, for progress notification When there is sufficient progress, and some amount of time has passed since the last progress notification, the resource contents will be updated with the new progress information, and a push notification will be given. 4. Client side work during upload, in progress notifications When there is progress, the javascript progress function will use the XMLHttpRequest to access the resource. The resource may contain a JSON data structure with the progress information for all of the files, as well as the total progress, if possible. Potentially the success/failure messages will be included as well. The user interface will be updated with this data. There will be a race condition, if the resource is in request scope, where the request will have finished, and the response will be transmitted to the browser, and in-between the browser may respond to push notifications, where the resource is no longer available. The client code should gracefully accept this, and do nothing. 5. Server side work after upload When rendering the fileEntry component after the uploads have completed, it should render the same UI that the progresses rendered, but with everything completed. And the registered resource should be set to depict everything as completed as well. 6. Client side work after upload When the component javascript gets the iframe updates after the upload, it should de-register itself from push notifications, so that the bridge may cease maintaining a blocking connection, if the fileEntry upload operation was the sole use of it.
        Hide
        Mark Collette added a comment -

        ICE-6303 is for testing with server push in auction monitor.

        Show
        Mark Collette added a comment - ICE-6303 is for testing with server push in auction monitor.
        Hide
        Mark Collette added a comment -

        Committed the plumbing code for having progress. The UI is not done, and there's a hard-coded dependence on icepush.jar.

        There were many challenges in getting this functionality accomplished:

        • Had to research how to register a dynamic resource with the new JSF 2 resource api
        • Instead of designing with a simple polling technique, had to design it to use the icepush library, so that it would work with the icepush socket, so that file uploads and progress notifications would work in applications that do pushes, like auctionMonitor
        • We want per fileEntry progress, in case there are multiple fileEntry components in the form, but also so we can get per file progress, but commons-upload does not report progress per file, but just for whole request. The reason being that multi-part doesn't actually describe how much data is coming, but just uses delimiters to say the file has ended. So, we decided to do a full submit progress, while showing the bytes per file. With HTML 5 we may be able to get the file size before upload, to then show per file progress.
        • We were using the JSF view state id to identify the fileEntry component uniquely within the session, for multiple reasons. But, it only sticks after the postback, so multiple accesses to it on the initial GET was causing it to change. So switched to ICEfaces viewId.
        • There was an issue where the javascript was not updating the page properly, because of duplicated spans, which wrap the script tag. This ended up being because of a bug in the code that rendered the script, where both our code and the default renderer were outputting span tags.
        • The whole form was getting updated, since it was getting dom differenced. That was due to the iframe being rendered near the end of the form for GET, and near the beginning of form for POST back.
        • Fixed javascript bug, which was causing onsubmit hadling to fail, so was doing full post without acting like an AJX post.
        • Unregistering the push id doesn't work smoothly when blocking for pushes. So I commented out unregistering for now
        • Browser hangs for minutes after upload, in Firefox when doing GETs. This started a whole round of further investigations to solve.
        • Put in code to limit how far the pushes get ahead of the gets, to reduce the duration of post-upload hanging
        • Added no cache headers to progress resource
        • Tried Post instead of Get, for accessing progress resource
        • Modified icepush library to add synchronous Get and Post, since the others were Async. Doesn't help, and seems slower. Ken and Mircea confirm that sync post/get is a bad idea
        • Tried polling method, where server pushes don't happen, and client doesn't register for push updates, and 2000 ms setTimeout makes it call the javascript onProgress function. Still didn't work well in Firefox.
        • Mircea and Ted have confirmed that it works well in their Firefox, so my setup is likely anomalous, so I should stop putting effort into solving this problem.

        Subversion 23299

        Show
        Mark Collette added a comment - Committed the plumbing code for having progress. The UI is not done, and there's a hard-coded dependence on icepush.jar. There were many challenges in getting this functionality accomplished: Had to research how to register a dynamic resource with the new JSF 2 resource api Instead of designing with a simple polling technique, had to design it to use the icepush library, so that it would work with the icepush socket, so that file uploads and progress notifications would work in applications that do pushes, like auctionMonitor We want per fileEntry progress, in case there are multiple fileEntry components in the form, but also so we can get per file progress, but commons-upload does not report progress per file, but just for whole request. The reason being that multi-part doesn't actually describe how much data is coming, but just uses delimiters to say the file has ended. So, we decided to do a full submit progress, while showing the bytes per file. With HTML 5 we may be able to get the file size before upload, to then show per file progress. We were using the JSF view state id to identify the fileEntry component uniquely within the session, for multiple reasons. But, it only sticks after the postback, so multiple accesses to it on the initial GET was causing it to change. So switched to ICEfaces viewId. There was an issue where the javascript was not updating the page properly, because of duplicated spans, which wrap the script tag. This ended up being because of a bug in the code that rendered the script, where both our code and the default renderer were outputting span tags. The whole form was getting updated, since it was getting dom differenced. That was due to the iframe being rendered near the end of the form for GET, and near the beginning of form for POST back. Fixed javascript bug, which was causing onsubmit hadling to fail, so was doing full post without acting like an AJX post. Unregistering the push id doesn't work smoothly when blocking for pushes. So I commented out unregistering for now Browser hangs for minutes after upload, in Firefox when doing GETs. This started a whole round of further investigations to solve. Put in code to limit how far the pushes get ahead of the gets, to reduce the duration of post-upload hanging Added no cache headers to progress resource Tried Post instead of Get, for accessing progress resource Modified icepush library to add synchronous Get and Post, since the others were Async. Doesn't help, and seems slower. Ken and Mircea confirm that sync post/get is a bad idea Tried polling method, where server pushes don't happen, and client doesn't register for push updates, and 2000 ms setTimeout makes it call the javascript onProgress function. Still didn't work well in Firefox. Mircea and Ted have confirmed that it works well in their Firefox, so my setup is likely anomalous, so I should stop putting effort into solving this problem. Subversion 23299
        Hide
        Mark Collette added a comment -

        Changed the usage of icepush to be conditional, so it would work without push present.

        Subversion 23303

        Show
        Mark Collette added a comment - Changed the usage of icepush to be conditional, so it would work without push present. Subversion 23303
        Hide
        Mark Collette added a comment -
        • Modified server side push code to force 100% progress to go to client, circumventing 2s update limitations, etc.
        • Investigated compat outputProgress markup and styling, and adapted to fileEntry progress markup
        • Created state machine of style classes
        • Changed resource contents to JSON data structure, including clientIds of active fileEntry components, so can set progress on them
        • Modified javascript to use progress info to update new markup ui
        • Simplified ui to not include percent text

        Subversion 23439

        Show
        Mark Collette added a comment - Modified server side push code to force 100% progress to go to client, circumventing 2s update limitations, etc. Investigated compat outputProgress markup and styling, and adapted to fileEntry progress markup Created state machine of style classes Changed resource contents to JSON data structure, including clientIds of active fileEntry components, so can set progress on them Modified javascript to use progress info to update new markup ui Simplified ui to not include percent text Subversion 23439
        Hide
        Mark Collette added a comment -

        Used compat Rime styling for outputProgress to make ACE Rime styling for fileEntry progress. Used compat Royale styling for outputProgress to make ACE Sam styling for fileEntry progress.

        Testing showed that if a form contained more than one fileEntry, where only one fileEntry was uploading, the non-uploading fileEntry was sticking in nondeterminate mode, after the upload. Fixed that, so that all fileEntry components in form would be cleaned up after upload.

        Tweaked style heights to better match image heights.

        Subversion 23461

        Show
        Mark Collette added a comment - Used compat Rime styling for outputProgress to make ACE Rime styling for fileEntry progress. Used compat Royale styling for outputProgress to make ACE Sam styling for fileEntry progress. Testing showed that if a form contained more than one fileEntry, where only one fileEntry was uploading, the non-uploading fileEntry was sticking in nondeterminate mode, after the upload. Fixed that, so that all fileEntry components in form would be cleaned up after upload. Tweaked style heights to better match image heights. Subversion 23461
        Hide
        Mark Collette added a comment -

        Removed server console debug

        Subversion 23465

        Show
        Mark Collette added a comment - Removed server console debug Subversion 23465
        Hide
        Mark Collette added a comment -

        Worked on using ACE sprite image support for fileEntry images. The sprite library did not support animated GIFs, so backed out efforts.

        Show
        Mark Collette added a comment - Worked on using ACE sprite image support for fileEntry images. The sprite library did not support animated GIFs, so backed out efforts.

          People

          • Assignee:
            Mark Collette
            Reporter:
            Mark Collette
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: