public void onScopeEnd ( @ Nonnull final ISessionScope aSessionScope ) { ValueEnforcer . notNull ( aSessionScope , "SessionScope" ) ; // Only handle scopes that are not yet destructed if ( aSessionScope . isValid ( ) ) { final String sSessionID = aSessionScope . getID ( ) ; final boolean bCanDestroyScope = m_aRWLock . writeLocked ( ( ) -> { boolean bWLCanDestroyScope = false ; // Only if we're not just in destruction of exactly this session if ( m_aSessionsInDestruction . add ( sSessionID ) ) { // Remove from map final ISessionScope aRemovedScope = m_aSessionScopes . remove ( sSessionID ) ; if ( ! EqualsHelper . identityEqual ( aRemovedScope , aSessionScope ) ) { LOGGER . error ( "Ending an unknown session with ID '" + sSessionID + "'" ) ; LOGGER . error ( " Scope to be removed: " + aSessionScope ) ; LOGGER . error ( " Removed scope: " + aRemovedScope ) ; } bWLCanDestroyScope = true ; } else LOGGER . info ( "Already destructing session '" + sSessionID + "'" ) ; return bWLCanDestroyScope ; } ) ; if ( bCanDestroyScope ) { // Destroy scope outside of write lock try { // Invoke SPIs ScopeSPIManager . getInstance ( ) . onSessionScopeEnd ( aSessionScope ) ; // Destroy the scope aSessionScope . destroyScope ( ) ; } finally { // Remove from "in destruction" list m_aRWLock . writeLocked ( ( ) -> m_aSessionsInDestruction . remove ( sSessionID ) ) ; } } } }
Close the passed session scope gracefully . Each managed scope is guaranteed to be destroyed only once . First the SPI manager is invoked and afterwards the scope is destroyed .