Package dyntabs.scope

Class TabScopePhaseListener

java.lang.Object
dyntabs.scope.TabScopePhaseListener
All Implemented Interfaces:
jakarta.faces.event.PhaseListener, Serializable, EventListener

public class TabScopePhaseListener extends Object implements jakarta.faces.event.PhaseListener
JSF PhaseListener that automatically sets the active tab scope at the appropriate point in the JSF lifecycle.

This is needed so that @TabScoped beans work correctly when accessed directly from EL expressions in XHTML pages (e.g. #{myTabBean}).

How it works:

  1. After RESTORE_VIEW phase, sets TabScopedContextHolder.currentTabId to the ID of the currently selected tab
  2. After RENDER_RESPONSE phase, clears currentTabId

IMPORTANT: Setting currentTabId is done after RESTORE_VIEW, NOT before it! Reason: @ViewScoped beans (DynTabManager, DynTabTracker) become available only AFTER RESTORE_VIEW completes and the view is created/restored. Attempting to access a @ViewScoped bean before that causes a ContextNotActiveException.

Registration: This listener is registered in faces-config.xml:

 
 <lifecycle>
     <phase-listener>dyntabs.scope.TabScopePhaseListener</phase-listener>
 </lifecycle>
 
 
Author:
DynTabs
See Also:
  • Constructor Details

    • TabScopePhaseListener

      public TabScopePhaseListener()
  • Method Details

    • afterPhase

      public void afterPhase(jakarta.faces.event.PhaseEvent event)
      Called after each JSF phase.

      After RESTORE_VIEW phase, sets currentTabId - this is the earliest point when @ViewScoped beans (DynTabManager) are available. This ensures that @TabScoped beans are active during ALL subsequent phases (APPLY_REQUEST_VALUES, UPDATE_MODEL_VALUES, INVOKE_APPLICATION, RENDER_RESPONSE), which is necessary for AJAX operations such as PrimeFaces pagination.

      After RENDER_RESPONSE phase, clears currentTabId to prevent tab context from "leaking" into the next request.

      Specified by:
      afterPhase in interface jakarta.faces.event.PhaseListener
      Parameters:
      event - PhaseEvent
    • beforePhase

      public void beforePhase(jakarta.faces.event.PhaseEvent event)
      Called before each JSF phase. Currently no action is needed before any phase.
      Specified by:
      beforePhase in interface jakarta.faces.event.PhaseListener
      Parameters:
      event - PhaseEvent
    • getPhaseId

      public jakarta.faces.event.PhaseId getPhaseId()
      Returns the PhaseId this listener should be activated for. ANY_PHASE means it will be activated for all phases (beforePhase and afterPhase for every phase).
      Specified by:
      getPhaseId in interface jakarta.faces.event.PhaseListener
      Returns:
      PhaseId.ANY_PHASE