Re: Object validation

From: Andrus Adamchik (andru..bjectstyle.org)
Date: Tue Jul 29 2003 - 10:04:13 EDT

  • Next message: Fabricio Voznika: "Re: Object validation"

    Hi Holger, Fabricio,

     Fabricio Voznika wrote:
    >> How are you guys doing validation in your objects using cayenne?
    >
    > Uhmm.. *looking at floor*..good question! :-)
    > There's not much (translation: almost nothing) in place for this right
    > now. The event stuff is there and works but it's not fully used yet.

    Before this is made a standard feature, validation can be easily
    implemented in a way external to Cayenne. I'll share some ideas below.

    >> The way I tried to do is to make my objects implement
    >> DataObjectTransactionEventListener.willCommit(DataContextEvent) and do
    >> all the checks there. But I haven't found a way to abort the commit
    >> from there. If I throw an exception, it just get logged (see
    >> Invocation.fire(Object[])) if I call DataContext.rollbackChanges() it
    >
    > Logging and subsequently ignoring any exceptions during event posting
    > was simply the first thing that came to my mind because I definitely
    > didn't want to abort the event loop just because one receiver bombed.
    > Handling the greater meaning of the exception is not the Invocation's
    > concern anyway, and the whole event machinery is meant to be as generic
    > as possible.

    Well, the way events are designed right now, they shouldn't be used for
    validation at all. I mean, there is a difference between "notification"
    and "delegation", even though in this case (each object validates itself)
    semantics is similar. So basically instead of forcing valdiation on event
    listeners, and allowing them to alter the flow, validation can work
    outside of the event dispatch.

    >
    > I think your best bet (for now) will be to manually check objects right
    > after modification. We definitely need a semi- (if not fully-)automagic
    > strategy for that before 1.0, but unfortunately there is no 'definite'
    > way to implement it since it often mixes business rules (model),
    > transaction logic (model/controller) and (in a web app) web application
    > state handling (controller). Even a manual way to abort 'the current
    > transaction' (whatever that is ;) might be a good first remedy, but
    > we'll need to discuss this with Andrus when he's back.

    For now I suggest doing something like this (and maybe contributing this
    to Cayenne if you feel like it ;-))

    1. Use persistent objects inheritance hierarchy like:
       MyObject extends _MyObject extends MyCayenneObject extends
    CayenneDataObject (modeler should support that)

    2. Implement a method like "MyCayenneObject.validateForSave(DataContext)"
    to do common validation on "this" - nulls, max width, etc. dynamically
    using DataMap to get the metadata. On failure throw an exception, or
    return a validation object similar to this:

    http://objectstyle.org/cayenne/api/cayenne/org/objectstyle/cayenne/project/validator/Validator.html

    that contains a list of these:

    http://objectstyle.org/cayenne/api/cayenne/org/objectstyle/cayenne/project/validator/ValidationInfo.html

    3. Optionally override validateForSave in all variations of MyObject to do
    business-specific validation (and calling super).

    4. Implement a static method somewhere (e.g. in MyCayenneObject) like:

      public static void commitChanges(DataContext ctxt) {
           Collection modified = ctxt.modifiedObjects();
           // call validateForSave on each one...

           Collection newObjects = ctxt.newObjects();
           // call validate for save on each one

           // not sure if we need to validate deleted?

           // do whatever needed if errors are found
           // ....

           // finally - commit if no errors
           ctxt.commitChanges();
      }

    This is very generic, uses only Cayenne public API and shouldn't be too
    hard to write (and in the futre plug into Cayenne core). There are few
    details up for discussion, like "throw an exception vs. return a
    validation object", or do both, etc...)

    What d'ya think?

    Andrus



    This archive was generated by hypermail 2.0.0 : Tue Jul 29 2003 - 10:04:15 EDT