Interceptors and events
It is often useful for the application to react to certain events that occur
inside Hibernate. This allows implementation of certain kinds of generic
functionality, and extension of Hibernate functionality.
Interceptors
The Interceptor interface provides callbacks from the session to the
application allowing the application to inspect and/or manipulate properties of a
persistent object before it is saved, updated, deleted or loaded. One
possible use for this is to track auditing information. For example, the following
Interceptor automatically sets the createTimestamp
when an Auditable is created and updates the
lastUpdateTimestamp property when an Auditable is
updated.
The interceptor would be specified when a session is created.
You may also set an interceptor on a global level, using the Configuration:
Event system
If you have to react to particular events in your persistence layer, you may
also use the Hibernate3 event architecture. The event
system can be used in addition or as a replacement for interceptors.
Essentially all of the methods of the Session interface correlate
to an event. You have a LoadEvent, a FlushEvent, etc
(consult the XML configuration-file DTD or the org.hibernate.event
package for the full list of defined event types). When a request is made of one of
these methods, the Hibernate Session generates an appropriate
event and passes it to the configured event listener for that type. Out-of-the-box,
these listeners implement the same processing in which those methods always resulted.
However, you are free to implement a customization of one of the listener interfaces
(i.e., the LoadEvent is processed by the registered implemenation
of the LoadEventListener interface), in which case their
implementation would be responsible for processing any load() requests
made of the Session.
The listeners should be considered effectively singletons; meaning, they are shared between
requests, and thus should not save any state as instance variables.
A custom listener should implement the appropriate interface for the event it wants to
process and/or extend one of the convenience base classes (or even the default event
listeners used by Hibernate out-of-the-box as these are declared non-final for this
purpose). Custom listeners can either be registered programmatically through the
Configuration object, or specified in the Hibernate configuration
XML (declarative configuration through the properties file is not supported). Here's an
example of a custom load event listener:
You also need a configuration entry telling Hibernate to use the listener instead
of the default listener:
...
]]>
Instead, you may register it programmatically:
Listeners registered declaratively cannot share instances. If the same class name is
used in multiple <listener/> elements, each reference will
result in a separate instance of that class. If you need the capability to share
listener instances between listener types you must use the programmatic registration
approach.
Why implement an interface and define the specific type during configuration? Well, a
listener implementation could implement multiple event listener interfaces. Having the
type additionally defined during registration makes it easier to turn custom listeners on
or off during configuration.
Hibernate declarative security
Usually, declarative security in Hibernate applications is managed in a session facade
layer. Now, Hibernate3 allows certain actions to be permissioned via JACC, and authorized
via JAAS. This is optional functionality built on top of the event architecture.
First, you must configure the appropriate event listeners, to enable the use of JAAS
authorization.
]]>
Next, still in hibernate.cfg.xml, bind the permissions to roles:
]]>
The role names are the roles understood by your JACC provider.