Interceptores y eventos Frecuentemente es útil para la aplicación reaccionar a ciertos eventos que ocurran dentro de Hibernate. Esto permite la implementación de ciertos tipos de funcionalidade genérica, y extensión de la funcionalidad de Hibernate. Interceptores La interface Interceptor provee callbacks desde la sesión a la aplicación permitiendo a ésta última inspeccionar y/o manipular las propiedades de un objeto persistente antes que sea salvado, actualizado, borrado o cargado. Un uso posible de esto es seguir la pista de información de auditoría. Por ejemplo, el siguiente Interceptor establece automáticamente el createTimestamp cuando un Auditable es creado y actualiza la propiedad lastUpdateTimestamp cuando un Auditable es acutalizado. El interceptor podría ser especificado cuando se crea la sesión: Puedes además establecer un interceptor a un nivel global, usando la Configuration: Sistema de eventos Si tienes que reaccionar a eventos particulares en tu capa de persistencia, puedes también la arquitectura de eventos de Hibernate3. El sistema de eventos puede ser usado en adición o como un remplazo a los interceptores. Esencialmente todos los métodos de la interface Session se correlacionan con un evento. Tienes un LoadEvent, un FlushEvent, etc (consulta el DTD del fichero de configuración XML o el paquete org.hibernate.event para la lista completa de tipos de evento definidos). Cuando se hace una petición de uno de estos métodos, la Session de Hibernate genera un evento apropiado y se lo pasa al oyente (listener) de eventos configurado para ese tipo. De fábrica, estos oyentes implementan el mismo procesamiento en los que siempre resultan aquellos métodos. Sin embargo, eres libre de implementar una personalización de una de las interfaces oyentes (es decir, el LoadEvent es procesado por la implementación registrada de la interface LoadEventListener), en cuyo caso su implementación sería responsable de procesar cualquier petición load() hecha a la Session. Los oyentes deben ser considerados efectivamente singletons; quiere decir, que son compartidos entre las peticiones, y por lo tanto no guardan ningún estado en variables de instancia. Un oyente personalizado debe implementar la interface apropiada para el evento que quiere procesar y/o extender una de las clases base de conveniencia (o incluso los oyentes de eventos por defecto usados por Hibernate de fábrica al ser éstos declarados non-final para este propósito). Los oyentes personalizados pueden ser registrados programáticamente a través del objeto Configuration, o especificados en el XML de configuración de Hibernate (la declaración declarativa a través del fichero de propiedades no está soportada). He aquí un ejemplo de un oyente personalizado de eventos load: Necesitas además una entrada de configuración diciéndole a Hibernate que use el oyente en vez del oyente por defecto: ... ]]> En cambio, puedes registrarlo programáticamente: Los oyentes registrados declarativamente no pueden compartir instancias. Si el mismo nombre de clase es usado en múltiples elementos <listener/>, cada referencia resultará en una instancia separada de esa clase. Si necesitas la capacidad de compartir instancias de oyentes entre tipos de oyente debes usar el enfoque de registración programática. ¿Por qué implementar una interface y definir el tipo espcífico durante la configuración? Bueno, una implementación de oyente podría implementar múltiples interfaces de oyente de eventos. Teniendo el tipo definido adicionalmente durante la registración lo hace más fácil para activar o desactivar oyentes personalizados durante la configuración. Seguridad declarativa de Hibernate Usualmente, la seguridad declarativa en aplicaciones Hibernate es manejada en una capa de fachada de sesión. Ahora, Hibernate3 permite que ciertas acciones sean permitidas vía JACC, y autorizadas vía JAAS. Esta en una funcionalidad opcional construída encima de la arquitectura de eventos. Primero, debes configurar los oyentes de eventos apropiados, para habilitar el uso de autorización JAAS. ]]> Seguido, aún en hibernate.cfg.xml, liga los permisos a roles: ]]> Los nombres de role son los roles entendidos por tu proveedor de JACC.