During RESTORE_VIEW, restoreState() is called from our BridgeSetup$NonTransientJavascriptResourceOutput:
public void restoreState(FacesContext context, Object state) {
//call method from super-class to restore the component attributes first
super.restoreState(context, state);
Map attributes = getAttributes();
String name = (String) attributes.get("name");
String library = (String) attributes.get("library");
String version = (String) attributes.get("version");
ResourceHandler resourceHandler = context.getApplication().getResourceHandler();
--> Resource r = resourceHandler.createResource(name, fixResourceParameter(library));
String path = r.getRequestPath();
if (version == null)
{
script = path;
}
else {
if (path.contains("?"))
{
script = path + "&v=" + version;
}
else
{
script = path + "?v=" + version;
}
}
}
The line we are interested in is the createResource() call which is marked with a -->. This method was added shortly after our 2.1 Beta 2 release so the code that leads to the issue was not being executed previous to the change.
The call to createResource() ends up going through all the ResourceHandlers until if finally hits org.portletfaces.bridge.application.ResourceHandlerImpl.createResource():
public Resource createResource(String resourceName, String libraryName, String contentType) {
FacesContext facesContext = FacesContext.getCurrentInstance();
BridgeFactoryFinder bridgeFactoryFinder = BridgeFactoryFinder.getInstance();
PortletContainerFactory portletContainerFactory = (PortletContainerFactory) bridgeFactoryFinder.getFactory(
BridgeFactoryFinder.PORTLET_CONTAINER_FACTORY);
BridgeContext bridgeContext = (BridgeContext) facesContext.getAttributes().get(Bridge.BRIDGE_CONTEXT_ATTRIBUTE);
--> PortletContainer portletContainer = portletContainerFactory.getPortletContainer(bridgeContext);
Resource wrappableResource = wrappedResourceHandler.createResource(resourceName, libraryName, contentType);
if (wrappableResource == null)
{
return new MissingResourceImpl(wrappedResourceHandler, resourceName, libraryName, contentType);
}
else
{
return new ResourceImpl(wrappableResource, portletContainer);
}
}
Part of the processing is to get an instance of the PortletContainer by using the factory. After it goes through the steps of determining a portlet container reference, the end of that method is:
if (portletContainer != null)
{
portletContainer.setPortletRequest(portletRequest);
portletContainer.setPortletResponse(portletResponse);
}
The process of setting the new portletRequest ends up replacing the current reference to our FileUploadPortletRequestWrapper So even though our wrapper is still "alive" and appears to have the correct data, it's no longer the request that is being used to retrieve all the relevant values - the request reference has been reset to point to the non-wrapped request.
Had a quick talk with Mark and there are likely several different ways to fix this:
1) During our wrapping and setting of the request, add some code to set it in two places to ensure it doesn't get swapped out. This would require some reflection to avoid having PortletFaces specific code in our File Entry logic.
2) Talk with Neil and see if there's a way so ensure that when the request is set to our wrapper, it doesn't inadvertently get set back.
3) Turn off the bit of our code in restoreState that calls createResource() which leads to the resetting of the request in PortletFaces.
I believe 1 and/or 3 are probably the correct places to tackle this but due to the tight timeline for releasing, we've gone with 2 for the time being. The code is constrained to the FileEntryPhaseListener and only comes into affect when running with portlets. A new JIRA will be opened to look at applying a different strategy in a future release.
Assigning to Mircea. Although the functionality of the component seems mostly intact, the update that follows the file upload should be handled without causing an exception.