Dashboard > Spring Modules > Persistent Object Life-cycle Event Validation pattern
  Spring Modules Log In View a printable version of the current page.  
  Persistent Object Life-cycle Event Validation pattern
Added by Steven Devijver, last edited by Steven Devijver on Jun 27, 2005  (view change)
Labels: 
(None)

In order to validate persistent objects within the life-cycle of ORM tools we need to be able to configure validators without putting this burden on the business logic. Each persistent class can have one or more validators configured per life-cycle event through a declarative configuration. This pattern does not aim to replace validation in other application tiers yet aims to ensure no invalid data is persisted to the database.

Introduction

When life-cycle events occur in the session of ORM tools we want to make sure no objects are persisted to the database without being verified by validators. To avoid custom coding of ORM tool callback interfaces the configuration of these validators must be done declaratively.

Configuration is done in two part:

  • configuration of validators per class and per life-cycle event
  • configuration of ORM tool specific callback class

The validator configuration class is an AOP method interceptor that takes a map of rule notations and validators. The callback class runs all validators against each peristent object for each supported and configured life-cycle event.

Configuration of validators

The org.springmodules.orm.support.validation.ValidatingMethodInterceptor class takes a map of rule notations and Spring validators (implementing the org.springframework.validation.Validator interface). The rule notations define which class uses which validator for which life-cycle event(s). A class can have multiple validators configured.

<bean id="validatingMethodInterceptor" class="org.springmodules.orm.support.validation.ValidatingMethodInterceptor">
   <property name="validators">
      <map>
         <entry key="foo.Bar,onSave,onFlushDirty">
            <ref bean="barSaveValidator"/>
         </entry>
         <entry key="foo.Bar,onDelete">
            <ref bean="barDeleteValidator"/>
         </entry>
         <entry key="foo.Bar">
            <ref bean="barGenericValidator"/>
         <entry>
      </map>
   </property>
</bean>

Rule notation

The rule notation takes a persistent class name plus optionally one or more life-cycle event names. These names are defined by the callback implementation per ORM tool thus making this configuration mechanism ORM tool agnostic. The names used in this example are supported by Hibernate.

foo.Bar configures a validator for all life-cycle events. foo.Bar,onSave,onFlushDirty configures a validator for the onSave and onFlushDirty life-cycle events. foo.Bar,onDelete configures a validator for the onDelete life-cycle event.

When validation fails

All configured validators are run against a persistent object per life-cycle event. When at least one validator fails to validate the persistent object a RuntimeException is thrown. By default org.springmodules.orm.support.validation.ValidationException is thrown. Users can however configure their own exception by implementing the org.springmodules.orm.support.validation.ErrorsToRuntimeExceptionTransformer interface. The errorsToRuntimeExceptionTransformer property of ValidatingMethodInterceptor takes a ErrorsToRuntimeExceptionTransformer instance.

Nested method interceptors

Multiple ValidatingMethodInterceptor instances can be configured in the Spring application context. When the method interceptor is executed it binds itself to the current thread. If other instances are executed within the call stack of the first instance the other instances will register themselves with the first instance and thus the first instance will not be removed from the current thread. This functionality ensures the total of all validators are considered when life-cycle event validation occurs.

Hibernate life-cycle callback implementations

Two Hibernate life-cycle callback implementations are available:

  • org.springmodules.orm.hibernate.support.ValidatingInterceptor - for Hibernate2
  • org.springmodules.orm.hibernate3.support.ValidatingInterceptor - for Hibernate3

These two life-cycle callback implementations behave in the same way. The following life-cycle events are supported:

  • onSave - before a persistent object is inserted into the database.
  • onFlushDirty - before a persistent object is updated in the database.
  • onDelete - before a persistent object is deleted from the database.

The onFlushDirty life-cycle event is the most important life-cycle event for Hibernate to which this pattern applies. When persistent objects are queried from the database or attached to the Hibernate session and are dirty there is not other callback mechanism available to make sure these object are validated before being persisted.

The onLoad life-cycle event is not supported since the object is not initialized when this event occurs in the Hibernate session.

Hibernate2 configuration

To configure Hibernate2 for the POLEV pattern add the ValidatingInterceptor to the session factory:

<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
   <property name="entityInterceptor">
      <bean class="org.springmodules.orm.hibernate.support.ValidatingInterceptor"/>
   </property>
</bean>

Hibernate3 configuration

To configure Hibernate3 for the POLEV pattern add the ValidatingInterceptor to the session factory:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
   <property name="entityInterceptor">
      <bean class="org.springmodules.orm.hibernate3.support.ValidatingInterceptor"/>
   </property>
</bean>

Might I recommend looking at the ChainedInterceptor support in the sandbox? This way we can take advantage of this class, plus the dependency injection interceptor, also found in sandbox.

Seth

Site running on a free Atlassian Confluence Open Source Project License granted to Spring Framework. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.5.5 Build:#811 Jul 25, 2007) - Bug/feature request - Contact Administrators