ICEfaces
  1. ICEfaces
  2. ICE-7685

ace:dataExporter sometimes fails in ACE Showcase when running as a portlet

    Details

    • Affects:
      Documentation (User Guide, Ref. Guide, etc.), Sample App./Tutorial

      Description

      When running the Date Exporter component as a portlet, the export throws an exception on the server and the file is never downloaded by the client. The problem occurs in with both Mojarra and MyFaces:

      Mojarra

      18:37:57,969 ERROR [ResourceImpl:81] Resource handler=[com.sun.faces.application.resource.ResourceHandlerImpl@71c54632] was unable to create a resource for resourceName=[s2] libraryName=[null] contentType=[null]

      MyFaces

      17:54:39,017 ERROR [ResourceImpl:81] Resource handler=[org.apache.myfaces.application.ResourceHandlerImpl@1d9ff8e2] was unable to create a resource for resourceName=[s3] libraryName=[null] contentType=[null]

        Issue Links

          Activity

          Hide
          Deryk Sinotte added a comment -

          The logging is coming from the PortletFaces Bridge as part of the MissingResourceImpl class.

          When the Export button is clicked, a response is sent back that includes some JavaScript, including the URL to be used to retrieve the resource. Seems that the URL created by the ICEfaces Data Exporter looks like the following:

          http://localhost:8080/web/guest/export?_dataExporter_WAR_showcaseportlet_javax.faces.resource=s2&p_p_col_count=1&p_p_col_id=column-1&p_p_id=dataExporter_WAR_showcaseportlet&p_p_lifecycle=2

          The resource name is not a real resource but a dynamic one that is a key to a real resource stored in the session. When the the PortletFaces Bridge tries to create a resource, I don't think it likes the fact that it's not a real file that it can get at.

          Show
          Deryk Sinotte added a comment - The logging is coming from the PortletFaces Bridge as part of the MissingResourceImpl class. When the Export button is clicked, a response is sent back that includes some JavaScript, including the URL to be used to retrieve the resource. Seems that the URL created by the ICEfaces Data Exporter looks like the following: http://localhost:8080/web/guest/export?_dataExporter_WAR_showcaseportlet_javax.faces.resource=s2&p_p_col_count=1&p_p_col_id=column-1&p_p_id=dataExporter_WAR_showcaseportlet&p_p_lifecycle=2 The resource name is not a real resource but a dynamic one that is a key to a real resource stored in the session. When the the PortletFaces Bridge tries to create a resource, I don't think it likes the fact that it's not a real file that it can get at.
          Hide
          Deryk Sinotte added a comment -

          This is the relevant stack trace to where the PFB finds that no resource has been created and therefore creates and instance of MissingResourceImpl:

          java.lang.Exception: Stack trace
          at java.lang.Thread.dumpStack(Thread.java:1273)
          at org.portletfaces.bridge.application.ResourceHandlerImpl.createResource(ResourceHandlerImpl.java:154)
          at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:110)
          at org.icefaces.impl.push.servlet.ICEpushResourceHandler.createResource(ICEpushResourceHandler.java:113)
          at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:110)
          at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:110)
          at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:110)
          at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:110)
          at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:110)
          at com.icesoft.faces.component.inputrichtext.InputRichTextResourceHandler.createResource(InputRichTextResourceHandler.java:182)
          at com.icesoft.faces.component.inputrichtext.InputRichTextResourceHandler.createResource(InputRichTextResourceHandler.java:166)
          at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:84)
          at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:84)
          at org.portletfaces.bridge.application.ResourceHandlerImpl.handleResourceRequest(ResourceHandlerImpl.java:193)
          at org.icefaces.impl.push.servlet.ICEpushResourceHandler$ICEpushResourceHandlerImpl.handleResourceRequest(ICEpushResourceHandler.java:224)
          at org.icefaces.impl.push.servlet.ICEpushResourceHandler.handleResourceRequest(ICEpushResourceHandler.java:126)
          at org.icefaces.impl.push.DynamicResourceDispatcher.handleResourceRequest(DynamicResourceDispatcher.java:77)
          at org.icefaces.application.ResourceRegistry.handleResourceRequest(ResourceRegistry.java:99)
          at org.icefaces.impl.application.WindowScopeManager.handleSessionAwareResourceRequest(WindowScopeManager.java:68)
          at org.icefaces.impl.application.SessionAwareResourceHandlerWrapper.handleResourceRequest(SessionAwareResourceHandlerWrapper.java:40)
          at org.icefaces.impl.application.SessionTimeoutMonitor.handleSessionAwareResourceRequest(SessionTimeoutMonitor.java:71)
          at org.icefaces.impl.application.SessionAwareResourceHandlerWrapper.handleResourceRequest(SessionAwareResourceHandlerWrapper.java:40)
          at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125)
          at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125)
          at org.icefaces.impl.application.AuxUploadResourceHandler.handleResourceRequest(AuxUploadResourceHandler.java:76)
          at org.portletfaces.bridge.BridgeImpl.doFacesRequest(BridgeImpl.java:508)

          My initial take is that, during the call to org.portletfaces.bridge.application.ResourceHandlerImpl.handleResourceRequest, it attempts to actually create the resource in order that it may call userAgentNeedsUpdate (for optimization reasons to avoid unecessary updates). However, since there is no actual resource (it's handled as a dynamic resource by ICEfaces and stored in the session using the resourceName as the key), the MissingResourceImpl logs the error and returns false.

          Show
          Deryk Sinotte added a comment - This is the relevant stack trace to where the PFB finds that no resource has been created and therefore creates and instance of MissingResourceImpl: java.lang.Exception: Stack trace at java.lang.Thread.dumpStack(Thread.java:1273) at org.portletfaces.bridge.application.ResourceHandlerImpl.createResource(ResourceHandlerImpl.java:154) at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:110) at org.icefaces.impl.push.servlet.ICEpushResourceHandler.createResource(ICEpushResourceHandler.java:113) at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:110) at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:110) at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:110) at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:110) at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:110) at com.icesoft.faces.component.inputrichtext.InputRichTextResourceHandler.createResource(InputRichTextResourceHandler.java:182) at com.icesoft.faces.component.inputrichtext.InputRichTextResourceHandler.createResource(InputRichTextResourceHandler.java:166) at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:84) at javax.faces.application.ResourceHandlerWrapper.createResource(ResourceHandlerWrapper.java:84) at org.portletfaces.bridge.application.ResourceHandlerImpl.handleResourceRequest(ResourceHandlerImpl.java:193) at org.icefaces.impl.push.servlet.ICEpushResourceHandler$ICEpushResourceHandlerImpl.handleResourceRequest(ICEpushResourceHandler.java:224) at org.icefaces.impl.push.servlet.ICEpushResourceHandler.handleResourceRequest(ICEpushResourceHandler.java:126) at org.icefaces.impl.push.DynamicResourceDispatcher.handleResourceRequest(DynamicResourceDispatcher.java:77) at org.icefaces.application.ResourceRegistry.handleResourceRequest(ResourceRegistry.java:99) at org.icefaces.impl.application.WindowScopeManager.handleSessionAwareResourceRequest(WindowScopeManager.java:68) at org.icefaces.impl.application.SessionAwareResourceHandlerWrapper.handleResourceRequest(SessionAwareResourceHandlerWrapper.java:40) at org.icefaces.impl.application.SessionTimeoutMonitor.handleSessionAwareResourceRequest(SessionTimeoutMonitor.java:71) at org.icefaces.impl.application.SessionAwareResourceHandlerWrapper.handleResourceRequest(SessionAwareResourceHandlerWrapper.java:40) at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125) at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125) at org.icefaces.impl.application.AuxUploadResourceHandler.handleResourceRequest(AuxUploadResourceHandler.java:76) at org.portletfaces.bridge.BridgeImpl.doFacesRequest(BridgeImpl.java:508) My initial take is that, during the call to org.portletfaces.bridge.application.ResourceHandlerImpl.handleResourceRequest, it attempts to actually create the resource in order that it may call userAgentNeedsUpdate (for optimization reasons to avoid unecessary updates). However, since there is no actual resource (it's handled as a dynamic resource by ICEfaces and stored in the session using the resourceName as the key), the MissingResourceImpl logs the error and returns false.
          Hide
          Deryk Sinotte added a comment -

          Checked in a fix for the ResourceRegistry where we try to extract the id of the dynamic resource. Instead of just parsing the various parts of the request URL for "javax.faces.resource", we also look at the parameter map as that where it is when the PortletFaces Bridge is managing things.

          Show
          Deryk Sinotte added a comment - Checked in a fix for the ResourceRegistry where we try to extract the id of the dynamic resource. Instead of just parsing the various parts of the request URL for "javax.faces.resource", we also look at the parameter map as that where it is when the PortletFaces Bridge is managing things.
          Hide
          Deryk Sinotte added a comment -

          Re-opening as the Export does not always work. It's fine if it's on a portal page by itself but in certain combinations with other portlets on the page, it will fail in the same way as originally descibed.

          Show
          Deryk Sinotte added a comment - Re-opening as the Export does not always work. It's fine if it's on a portal page by itself but in certain combinations with other portlets on the page, it will fail in the same way as originally descibed.
          Hide
          Deryk Sinotte added a comment -

          This will become a known issue for this release as we try to determine the specific conflict that prevents it from working in only certain situations.

          Show
          Deryk Sinotte added a comment - This will become a known issue for this release as we try to determine the specific conflict that prevents it from working in only certain situations.
          Hide
          Deryk Sinotte added a comment -

          So it seems that the reliable way to reproduce the problem is to

          • deploy a DataExporter instance to two different portal pages (no other portlets are required)
          • navigate to one of the portal pages and export a file (should work)
          • navigate to the other portal page and export a file (should fail)

          15-Feb-2012 7:48:52 PM com.sun.faces.application.resource.ResourceHandlerImpl logMissingResource
          WARNING: JSF1064: Unable to find or serve resource, s3.
          19:48:52,091 ERROR [ResourceImpl:81] Resource handler=[com.sun.faces.application.resource.ResourceHandlerImpl@6e071c58] was unable to create a resource for resourceName=[s3] libraryName=[null] contentType=[null]

          It looks like there may be some confusion as to the type or scope of the session that the resource belongs to when running as a portlet.

          Show
          Deryk Sinotte added a comment - So it seems that the reliable way to reproduce the problem is to deploy a DataExporter instance to two different portal pages (no other portlets are required) navigate to one of the portal pages and export a file (should work) navigate to the other portal page and export a file (should fail) 15-Feb-2012 7:48:52 PM com.sun.faces.application.resource.ResourceHandlerImpl logMissingResource WARNING: JSF1064: Unable to find or serve resource, s3. 19:48:52,091 ERROR [ResourceImpl:81] Resource handler= [com.sun.faces.application.resource.ResourceHandlerImpl@6e071c58] was unable to create a resource for resourceName= [s3] libraryName= [null] contentType= [null] It looks like there may be some confusion as to the type or scope of the session that the resource belongs to when running as a portlet.
          Hide
          Deryk Sinotte added a comment -

          When something like the CSVExporter adds a resource to the ResourceRegistry:

          String path = ResourceRegistry.addSessionResource(resource);

          It gets added to the relevant map scoped for that resource - in this case the session map:

          ResourceRegistryHolder holder = new ResourceRegistryHolder(key, resource);
          scopeMap.put(MAP_PREFIX + key, holder);

          However, to pull it back out, we use this bit of code:

          ResourceRegistryHolder holder = (ResourceRegistryHolder) elContext.getELResolver().getValue(elContext, null, MAP_PREFIX + key);

          So while the resource is in the portlet session, the ElContext isn't able to resolve the value when the second DataExporter is run.

          Show
          Deryk Sinotte added a comment - When something like the CSVExporter adds a resource to the ResourceRegistry: String path = ResourceRegistry.addSessionResource(resource); It gets added to the relevant map scoped for that resource - in this case the session map: ResourceRegistryHolder holder = new ResourceRegistryHolder(key, resource); scopeMap.put(MAP_PREFIX + key, holder); However, to pull it back out, we use this bit of code: ResourceRegistryHolder holder = (ResourceRegistryHolder) elContext.getELResolver().getValue(elContext, null, MAP_PREFIX + key); So while the resource is in the portlet session, the ElContext isn't able to resolve the value when the second DataExporter is run.
          Hide
          Ted Goddard added a comment -

          Setting session scoped resources as attributes on getSafeSession and pulling them out using getSafeSession resolves this. The root cause appears to be a race condition in the maintenance of the SessionMap in the PortletFaces Bridge. This can be debugged by enabling FINE logging on ResourceRegistry: when the normal SessionMap lookup fails, "Resource lookup required direct sesssion access" will be printed to the log.

          Show
          Ted Goddard added a comment - Setting session scoped resources as attributes on getSafeSession and pulling them out using getSafeSession resolves this. The root cause appears to be a race condition in the maintenance of the SessionMap in the PortletFaces Bridge. This can be debugged by enabling FINE logging on ResourceRegistry: when the normal SessionMap lookup fails, "Resource lookup required direct sesssion access" will be printed to the log.

            People

            • Assignee:
              Deryk Sinotte
              Reporter:
              Deryk Sinotte
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: