SessionListener.java

/*
** Module   : SessionListener.java
** Abstract : Interface for objects interested in session life cycle events
**
** Copyright (c) 2004-2017, Golden Code Development Corporation.
**
** -#- -I- --Date-- --JPRM-- ----------------------------Description-----------------------------
** 001 ECF 20060901   @30523 Created initial version. Interface for
**                           objects interested in receiving Hibernate
**                           session life cycle events (initially only a
**                           session closing event is supported).
** 002 ECF 20070602   @33928 Added new scope constants. GLOBAL_SCOPE and
**                           NO_SCOPE.
** 003 ECF 20070706   @34404 Added deregisteredSessionListener() to API.
**                           Provides a notification to listener when it is
**                           deregistered.
** 004 ECF 20090810   @43592 Refactored API to support arbitrary event types.
**                           Replaced sessionClosing() with sessionEvent().
**                           Added public enums for event types and scope of
**                           registration.
** 005 ECF 20160409          Added SESSION_CLEANUP event type.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
** 
** Additional terms under GNU Affero GPL version 3 section 7:
** 
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
**   terms apply to the works covered under the License.  These additional terms
**   are non-permissive additional terms allowed under Section 7 of the GNU
**   Affero GPL version 3 and may not be removed by you.
** 
**   0. Attribution Requirement.
** 
**     You must preserve all legal notices or author attributions in the covered
**     work or Appropriate Legal Notices displayed by works containing the covered
**     work.  You may not remove from the covered work any author or developer
**     credit already included within the covered work.
** 
**   1. No License To Use Trademarks.
** 
**     This license does not grant any license or rights to use the trademarks
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
**     of Golden Code Development Corporation. You are not authorized to use the
**     name Golden Code, FWD, or the names of any author or contributor, for
**     publicity purposes without written authorization.
** 
**   2. No Misrepresentation of Affiliation.
** 
**     You may not represent yourself as Golden Code Development Corporation or FWD.
** 
**     You may not represent yourself for publicity purposes as associated with
**     Golden Code Development Corporation, FWD, or any author or contributor to
**     the covered work, without written authorization.
** 
**   3. No Misrepresentation of Source or Origin.
** 
**     You may not represent the covered work as solely your work.  All modified
**     versions of the covered work must be marked in a reasonable way to make it
**     clear that the modified work is not originating from Golden Code Development
**     Corporation or FWD.  All modified versions must contain the notices of
**     attribution required in this license.
*/

package com.goldencode.p2j.persist.event;

import com.goldencode.p2j.persist.*;

/**
 * Implemented by classes whose instances need to know about session life
 * cycle events as they happen.
 * <p>
 * The following events generate notifications:
 * <ul>
 *   <li>TRANSACTION_COMMITTING - the current database-level transaction is
 *       about to be committed.</li>
 *   <li>SESSION_CLOSING_NORMALLY - the current Hibernate session is about to
 *       be closed due to normal processing (no error).</li>
 *   <li>SESSION_CLOSING_WITH_ERROR - the current Hibernate session is about
 *       to be closed due to an error.</li>
 * </ul>
 * <p>
 * <code>SessionListener</code> instances are registered with the {@link
 * Persistence} class.  They are not explicitly deregistered, but rather are
 * implicitly deregistered at the end of a specific scope (or possibly
 * earlier -- see below).  A listener's scope is determined at registration
 * time using one of the following <code>Scope</code> types.
 * <ul>
 *   <li>NONE - the listener is never deregistered and survives until the end
 *       of the client context.
 *   <li>GLOBAL - deregister the listener when the context's global scope
 *       ends.  This corresponds with the end of the user session.
 *   <li>ENCLOSING_EXTERNAL - deregister the listener when the current,
 *       external scope ends.  This corresponds to the enclosing, external
 *       procedure scope in Progress.
 *   <li>CURRENT - deregister the listener when the current block scope ends.
 *   <li>NEXT_EXTERNAL - deregister the listener when the next external scope
 *       to be opened ends.  This corresponds to an external procedure in
 *       Progress, but not one we currently are in.  Care must be taken when
 *       using this scope;  it presumes that the next external scope to be
 *       opened actually corresponds with the life cycle of the listener.
 *       The idiom with which this usage typically corresponds is the
 *       construction of a business logic object, followed by the immediate
 *       invocation of its primary entry point method (usually called
 *       <code>execute</code>).  This is meant to support listener objects
 *       which are constructed as instance members of the business logic
 *       object.  We can get into trouble if some other, external scope is
 *       opened between the construction of our business logic object and the
 *       invocation of its <code>execute()</code> method.  This will not
 *       happen in converted code, but it is possible in hand-written code.
 * </ul>
 * <p>
 * There are two ways a session listener may be deregistered earlier than at
 * end of the scopes described above:
 * <ul>
 *   <li>If the listener object is no longer referenced by business logic, it
 *       may be collected at any time by the garbage collector.
 *   <li>If the listener's {@link #sessionEvent} method returns
 *       <code>true</code>, the listener is deregistered immediately after
 *       this method returns.
 * </ul>
 */
public interface SessionListener
{
   /** Type of session event */
   public enum Event
   {
      /** Transaction is about to be committed */
      TRANSACTION_COMMITTING,
      
      /** Session is not closing, but requires cleanup */
      SESSION_CLEANUP,
      
      /** Session is about to close normally */
      SESSION_CLOSING_NORMALLY,
      
      /** Session is about to close due to an error */
      SESSION_CLOSING_WITH_ERROR,
   };
   
   /** Scope of listener registration */
   public enum Scope
   {
      /** Never deregister the session listener */
      NONE,
      
      /** Scope listener registration to context's global scope */
      GLOBAL,
      
      /** Scope listener registration to enclosing external block scope */
      ENCLOSING_EXTERNAL,
      
      /** Scope listener registration to current block scope */
      CURRENT,
      
      /** Scope listener registration to next (lower) external block scope */
      NEXT_EXTERNAL,
   };
   
   /**
    * Invoked when a significant event occurs related to the current Hibernate
    * session or transaction.
    * 
    * @param   event
    *          Type of event.
    * 
    * @return  <code>true</code> if this listener should be removed from the
    *          current set of registered listeners;  <code>false</code> to
    *          remain registered.
    * 
    * @throws  PersistenceException
    *          if any error occurs during the implementor's processing of the
    *          given event.  If this exception is thrown, the listener will be
    *          deregistered as if <code>true</code> had been returned.
    */
   public boolean sessionEvent(Event event)
   throws PersistenceException;
   
   /**
    * Invoked when a session listener is removed from the list of registered
    * session listeners.  This method is invoked due to deregistration at the
    * end of the associated scope and after {@link
    * #sessionEvent(com.goldencode.p2j.persist.event.SessionListener.Event)}
    * is invoked and returns <code>true</code>.  It is <i>not</i> invoked when
    * deregistration occurs due to garbage collection, since the listener is
    * not in a position to do anything useful at that point anyway, and is no
    * longer referenced by business logic.
    */
   public void deregisteredSessionListener();
}