Don’t persist UIComponent state in the session


Our use case was as followed: In our WebCenter Portal application we have a tableform layout, with a panelAccordion on the form layout. For other functionality we needed MDS persistence to be on, so we couldn’t disable MDS customizations. A side effect was that the panelAccordion remembered the showDetailItem that was disclosed and reopened the form page on the previously disclosed tab. 

We have the Seeded Customizations enabled, you can do this through the project properties:
 This results in a web.xml entry:
  
    org.apache.myfaces.trinidad.CHANGE_PERSISTENCE
    oracle.adf.view.page.editor.change.ComposerChangeManager
  
Now we can configure our adf-config file to exclude Persist Changes:

However, this doesn’t help you for your current session. We can see in the JavaDoc from the FilteredPersistenceChangeManager, the following documentation:
If the DocumentChange fails through the restriction, the corresponding ComponentChange is persisted to the Session.

We also don’t want to persist the changes in the session, so we had to subclass the ComposerChangeManager and override the addComponentChange method:
public class PortalComposerChangeManager extends ComposerChangeManager
{
  /**
   * adf-config.xml still persist in session, @see FilteredPersistenceChangeManager
   * We don't want this for the showDetailItem in the RichPanaelAccordion.
   *
   * @param context the FacesContext.
   * @param component the UIComponent.
   * @param change the ComponentChange.
   */
  @Override
  public void addComponentChange(FacesContext context, UIComponent component,
                                 ComponentChange change)
  {
    if (component instanceof RichShowDetailItem &&
        ((RichShowDetailItem) component).getParent() instanceof RichPanelAccordion &&
        change instanceof AttributeComponentChange &&
        "disclosed".equals(((AttributeComponentChange) change).getAttributeName()))
    {
      logger.fine("ComponentChange; disclosed event on showDetailItem in a RichPanelAccordion, we don’t persist.");
      return;
    }
    super.addComponentChange(context, component, change);
  }
}

This method is called by the framework to persist the component change. We override this method and  check if the component is a RichShowDetailItem in a RichPanelAccordion. If the ComponentChange is also a disclosed event, we don't call the super, so this change doesn't persist.

Since I don’t have my Oracle Cloud Trial anymore, I included a workspace, which reproduces this behavior. 
You can see the difference between the two accordions by changing the web.xml parameter. State is saved in session with the default web.xml param:

    Change Persistence Parameter
    org.apache.myfaces.trinidad.CHANGE_PERSISTENCE
    oracle.adf.view.page.editor.change.ComposerChangeManager
  

You can see the panelAccordion resetting to the first showDetailItem when you change to this parameter: 

    Change Persistence Parameter
    org.apache.myfaces.trinidad.CHANGE_PERSISTENCE
    nl.olrichs.blog.panelmds.portal.view.change.PortalComposerChangeManager
  


All you need to do for reproducing is:
  • Click the button toPanelAccordion.
  • Open a different showDetailItem.
  • Click the back button.
  • Click the button toPanelAccordion again.