I have spent some time reading BalusC's answer on this question but I can't seem to apply that knowledge to my situation. I am also getting the ViewExpiredException but only under certain circumstances.
My page is backed by a @ViewScoped bean and uses two p:layoutUnits to display a p:tree (west) with the contents of the folder in the center pane. Selecting a folder in the tree triggers an AJAX event to update the center pane with the contents of the selected folder. The skeleton of the JSF is as follows:
<p:layout id="workLayout">
<p:layoutUnit id="paneTree"
position="west"
size="200">
<h:form id="treeForm">
<p:tree value="#{workspace.listTree}"
var="node"
dynamic="true"
selectionMode="single"
>
<p:ajax event="select"
listener="#{workspace.onNodeSelect}"
update="panelData"
/>
<p:treeNode>
<h:outputText value="#{node.name}" />
</p:treeNode>
</p:tree>
</h:form>
</p:layoutUnit>
<p:layoutUnit id="paneData"
position="center"
resizable="true">
<h:panelGroup id="panelData" >
<h:form id="formData" rendered="#{workspace.selected ne null}">
<h2>#{workspace.selected.name}: #{workspace.selected.title}</h2>
<p>
<div id="divImages"
style="width: 49%; height: 99%; float: right">
<p:panel rendered="#{empty workspace.listImages}">
<p>No Images In This List.</p>
</p:panel>
<ui:repeat value="#{workspace.listImages}"
var="img"
>
<p>
#{img.name}: #{img.title}
</p>
<img src="#{workspace.getUrl(img)}"
style="max-width: 250px"
/>
<hr/>
</ui:repeat>
</div>
<div id="divDocs"
style="width: 49%; height: 99%; float: left">
<p:dataTable id="tableFiles"
value="#{workspace.listDocuments}"
>
<p:column ...
<p:column ...
<p:column ...
</p:dataTable>
</div>
</p>
</h:form>
</h:panelGroup>
</p:layoutUnit>
The trouble starts when you select a folder that has a few images in it. As little as 10 or fewer images is enough to create the problem. This causes the ui:repeat element to render the number of img tags, each with a URL that loads an image.
The URL triggers a Servlet in the application that the same CDI domain so it can inject the same resources as the managed beans do. The Servlet responds with just a response header with the MIME type and the data. However each img access creates a new @SessionScoped bean -- the same one this JSF page uses. It does not get the same instance as the JSF page and the various img accesses do not share a session bean between them either. Each access generates a new one.
The Servlet looks like this:
@WebServlet(name = "Obj", urlPatterns = {"/obj/*"})
public class Obj extends HttpServlet {
@Inject ProtoObjectControl poc;
@Inject UserSession us;
The UserSession is the @SessionScoped object that contains login information (which is not logged in since it always generates a new one) and various utilities like the log functions. The ProtoObjectControl is a DAO object to fetch the image to display.
The end result is that the page that did the display ends up crashing with a ViewExpiredException. I think this is because the explosion of sessions is consuming resources that are getting exhuasted. If I take out the img tag and run the page with that the ViewExpiredException never comes up and the page works as reliably as Mac Finder or Windows File Explorer.
So is there any way to explain why this happens and to engineer around it? I want to not have a limit on the number of images that can come up in the display. Ideally I would like to have the Servlet access the same UserSession bean as the JSF page -- it is after all being accessed from the same client -- but perhaps that is not possible. Is there any other approach?