Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: 1.8.2-EE-GA_P02
-
Fix Version/s: 1.8.3, EE-1.8.2.GA_P03
-
Component/s: ICE-Components
-
Labels:None
-
Environment:Cookies disabled on server and browser. Tomcat: context.xml -> <Context cookies="false"/>
-
Workaround Exists:Yes
-
Workaround Description:When apps disable session cookies in their context.xml file, they should also set the com.icesoft.faces.forceLifecycleOnCallingThread context param to true. And possibly set their app to synchronous mode, since server push might depend on cookies.
Description
When cookies are disabled on the server and the browser the inputFile disappears when a file is uploaded. The file is saved properly and no errors are thrown. A refresh of the browser shows the component again.
There is a difference in behavior depending on the browser and cookie settings.
Firefox:
- Cookies disabled on the server and browser: inputFile does not disappear on upload.
- Cookies disabled on the severe but not on the browser: inputFile disappears on upload.
IE:
- Component disappears no matter what the browser cookies setting is.
There is a difference in behavior depending on the browser and cookie settings.
Firefox:
- Cookies disabled on the server and browser: inputFile does not disappear on upload.
- Cookies disabled on the severe but not on the browser: inputFile disappears on upload.
IE:
- Component disappears no matter what the browser cookies setting is.
Issue Links
- depends on
-
ICE-5871 Add a configuration parameter for turning on URL rewriting
- Closed
Using the test application and tomcat 6, I duplicated the issue. Sometimes the inputFile's iframe would disappear after several uploads and sometimes it would disappear after one upload. I investigated
ICE-5871, and audited the inputFile code to confirm that it does indeed use ExternalContext.encodeResourceURL(String) to render both the URL for the iframe source in the larger page, and within the iframe page for its posting. Viewing the browser dom shows that the initial page GET includes the jsessionid part in the urls, but that after one or more upload POSTs the jsessionid is not there anymore, and the iframe disappears. Further investigation in the core shows that com.icesoft.faces.webapp.http.servlet.ServletExternalContext.encodeResourceURL(String) is responsible for delegating to the Response.encodeURL(String). Modification of that method showed that the Catalina classes were throwing an exception, and our code was silently trapping it and using the unencoded url, when we were losing the jsessionid part. The stack trace indicated that it was while doing a PersistentFacesState.renderLater() for pushing updates.Disabling delayed rendering, that occurs on a separate thread, in favour of immediate rendering that happens on the current thread, seems to fix the issue. The jsessionid part remains after many uploads. The easiest way to accomplish this is for cookie-less apps to set the com.icesoft.faces.forceLifecycleOnCallingThread context param to true. Support are testing to ensure this works for all browsers, as IE had given different results than Firefox.
For future reference, in case something related to this pops up again, here's more analysis. At the end of the file upload, the iframe contents need to be written out to the response object, so we do a lifecycle to get the contents. Currently, that lifecycle can use immediate rendering or deferred rendering, just like all the progress pushes. It's probably best to use the same technique, so they'll be queued appropriately. We wouldn't want to make our last render be immediate, and then queued progress pushes come in later, if that could somehow show older progress. But if we did make the last lifecycle be immediate, and used that to stop any other async ones that hadn't come through yet, that might also solve the issue of UploadServer.getResultingIframeContent making long running actionListeners have the iframe disappear. We could also see why the 5 second timeout is so short. Perhaps browsers do a timeout without any response by then anyway. If we wrote out some headers, then did the lifecycle, and let it run for however long, and made it immediate, then perhapse we'd get around it. Also, it seems like there's a bit of an issue where the lifecycle should cause the page to update before we return the iframe contents. But most likely the dom diff keeps that from updating that part of the page anyway.