Greetings,
I have rich faces application (3.3.2.SR1). The application uses ModelPanel to view entities. All modal panels are not rendered until I want to show them (rendered = false). Application becomes to be big, and uses a lot relations from one panel to others. All works fine, but it looks like richfaces creates UIComponent tree in memory for all possible cases if component rendred is true or false. When I tried to check memory usage of application (I used YourKit Java Profiler for these needs) I see that it uses a lot of memory for one session.
I am using Facelets together with richfaces and I tried to use
<c:if test="rendred condition"... /> content </c:if>
It starts to use significantly less memory, but... when I rerender the area with panel, controls on parent screen are stopped to work. I suspect that it is because of every time when component tree is changed it recreates whole tree, and I have unsynchronized client (html) and server (faces) parts.
Could somebody suggest me the way how to reduce memory usage? I have real problem with it as StandardSession object in HeapMemory uses 60-150Mb. And almost all of this memory used for UIControls.
Example of the problem:
I have page which has references to panel1, panel2, panel3.
Panel is:
<rich:modalPanel >
<a4j:outputPanel layout="block"
rendered="#{PanelBeanHolder.renderedViewScreen}">
<ui:insert name="panelContent" />
</a4j:outputPanel>
</rich:modalPanel>
I am rendering panel only when action for this is performed. And do not want to load the UI controls for output panel until I need it.
Thank you in advance.
P.S. I tried to do the following to improve the situation
Configure number of views in session inside web.xml with:
<context-param>
<param-name>com.sun.faces.numberOfViewsInSession</param-name>
<param-value>4</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.numberOfLogicalViews</param-name>
<param-value>4</param-value>
</context-param>
It has to improve StateHolder object, but it doesn't help a lot. I did measuring and memory usage is grows when these number are grow. But, when i tired to set them to 1,1 - some pages stopped work. Sometimes request is forwarded to the welcome page. 2,2 improved the situation, but the issue with forwarding to welcome pages still happens.
Tried to use client mode in javax.faces.STATE_SAVING_METHOD. It still uses a lot of memory for UIComponent model. Even if objects are serialised and have to be stored in the form.
Tried to rewrite stateManager in faces.config:
<state-manager>org.ajax4jsf.application.CompressAjaxStateManager</state-manager>
and rewrite buildViewState and restoreView for compressing the stream. It doesn't help a lot.
JSF uses a stateful component tree that is maintained between requests. By default, this is usually maintained in the session. There are features you can use to control this.
Configure state saving parameters
There are usually implementation-specific parameters to control the number of views stored in the session - depending on how your application behaves, this might be an easy win.
You can save the state in forms using the javax.faces.STATE_SAVING_METHOD
parameter. However, be aware you're sending more information per request and there are security risks in allowing the client to dictate server-side state (ensure you are happy with how your implementation encrypts this data). You will need to check compatibility with your component libraries (i.e. RichFaces), especially if you're using AJAX.
JSF 2 uses a new state-saving mechanism that reduces the session overhead; your faces-config.xml
will need to be updated to the 2.0 version. I believe this idea came from Apache Trinidad, so you may be able to extract a pre-JSF 2 version from there.
Do your own state saving and/or view creation
Implementing your own StateManager
and/or ViewHandler
lets you take programmatic control over how views are handled. For example, you could write a StateManager
that persisted views to a database (with appropriate time-out and clean-up).
Use component binding and transient controls
You can take programmatic control over how components are created. From the spec on binding:
- When a component instance is first created (typically by virtue of being referenced by a
UIComponentELTag
in a JSP page), the JSF implementation will retrieve theValueExpression
for the name binding, and callgetValue()
on it. If this call returns a non-nullUIComponent
value (because the JavaBean programmatically instantiated and configured a component already), that instance will be added to the component tree that is being created. If the call returns null, a new component instance will be created, added to the component tree, andsetValue()
will be called on theValueExpression
(which will cause the property on the JavaBean to be set to the newly created component instance).- When a component tree is recreated during the Restore View phase of the request processing lifecycle, for each component that has a
ValueExpression
associated with the name “binding”,setValue()
will be called on it, passing the recreated component instance.
You could probably use this with the transient property on children to control programmatically control creation/destruction of child components. This is manual and a bit messy, but might work in extreme cases.
I'm sure this isn't an exhaustive list.