-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: How is everyone handling validation?
PostPosted: Mon Oct 10, 2005 6:34 am 
Senior
Senior

Joined: Sat Sep 03, 2005 12:54 am
Posts: 139
Hi,

I am having trouble finding info on the best way to handle validation of domain objects in the NH world.

The documenation states the following:

"Unlike the callback methods of the Lifecycle interface, validate() might be called at unpredictable times. The application should not rely upon calls to validate() for business functionality."

Not sure exactly what is meant by "The application should not rely upon calls to validate() for business functionality"!! Can this interface be used for validation or not!!? :?

Is the ILifecycle interface a better option? Does this have any limitations that prevent it from being used to validate objects before they are persisted to the DB?

Thanks,

Jason


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 12:40 pm 
Senior
Senior

Joined: Sat Sep 10, 2005 3:46 pm
Posts: 178
I have the same issues with IValidatable. Whats the point of it if you can't rely on it. Seems pretty useless to me for entity validation. The problem with ILifecycle is that Update is not called everytime the object's persitent state is updated. So ILifecycle seems to be no good for the purpose of making sure an object is valid before it is persisted.

I think what you have to do is create an Interface for entities that expose an IsValid property. then you need an interceptor that checks the IsValid property of the entity. If IsValid is false then you cancel the operation. You have to peform any validation that requires access to persistent data before the Interceptor calls the IsValid property though, because I know that you can't or should not access the session for certain operations of the interceptor. So this limitation forces you to create a Validate operation on your entity that will call validation operations that require a session.

That's what Ive come up with so far. Its not the perfect solution but it does the job. I'd be interested to hear of other cleaner alternatives.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 3:16 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Actually I believe Hibernate developers acknowledge in Hibernate in Action that ILifecycle and IValidatable were bad ideas, and that one should instead use IInterceptor when possible. Or you can try doing validation in getters/setters to prevent an object from ever entering invalid state.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 4:21 pm 
Senior
Senior

Joined: Sat Sep 03, 2005 12:54 am
Posts: 139
It would appear that you do not have access to the session in IInterceptor though...is that correct?

One problem is that sometimes validation needs to check against other domain objects, e.g. to enforce uniqueness, so you really need to have access to the session. This would seem to make it difficult to add this type of validation to the getters and setters too. A workaround I guess would be to open a second session but that seems pretty crazy.

I also prefer to validate the entire object in one go so that you can collect all the errors and report these back to the user as a set rather than reporting one error at a time. This is particularly beneficial in a web environment when you are posting back to the server every time.

I am surprised to hear that "Hibernate developers acknowledge in Hibernate in Action that ILifecycle and IValidatable were bad ideas"!! They seem like a good idea if they were to function correctly! The ILifecycle concept seems perfect as it has access to the session and has methods for each of the key actions that can be performed against an object...why is this a bad idea?

Thanks,

Jason


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 7:23 pm 
Contributor
Contributor

Joined: Sat Sep 24, 2005 11:25 am
Posts: 198
sergey wrote:
Actually I believe Hibernate developers acknowledge in Hibernate in Action that ILifecycle and IValidatable were bad ideas, and that one should instead use IInterceptor when possible. Or you can try doing validation in getters/setters to prevent an object from ever entering invalid state.


I read Hibernate in Action, and I agree in principal, but...

I'm using ILifecycle to load a part of the domain model that is not under NHib control. This is spesific for every domain object, so I think that it deserves the special treatment. Comment?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 2:55 am 
Beginner
Beginner

Joined: Thu May 12, 2005 2:14 am
Posts: 33
Location: Sweden, Sk
sergey wrote:
Actually I believe Hibernate developers acknowledge in Hibernate in Action that ILifecycle and IValidatable were bad ideas, and that one should instead use IInterceptor when possible. Or you can try doing validation in getters/setters to prevent an object from ever entering invalid state.


Hi

Im also struggling with this. The problem with this argument is that sometimes a object is in a invalid state. When I create an object the object is invalid and contains errors.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 9:39 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
IMO, NHibernate is an ORM; and handling validation is not one of the (main) objectives of an ORM. It can try to provide a solution, but it is better for an application to have its own way to perform validation (independently of the ORM).

Don't forget that the premiere reason of using an (non-instrusive) ORM is that it frees your entities from knowing that they are ever persisted; and relying on the ORM for validation can make unit-testing your DomainModel a nightmare... :twisted:

Anyway, ILifecycle, IValidatable and IInterceptor are here to help doing that, so they should do their job correctly :wink: I can't help you on that because I have never used them.

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 3:53 pm 
Senior
Senior

Joined: Sat Sep 10, 2005 3:46 pm
Posts: 178
I agree that NHibernate should not be responsible for doing the validation but since it works as a Unit of Work invalid data could potenitally be persisted if there is no way to stop NHibernate from persisting invalid objects.

The main problem of ILifecycle is that OnUpdate cant be guranteed to be called.

Take this example:

I have user and company entities. I change an existing user's email address, the email address that I change it to is not unique within the system, yet I have not validated the entity yet, doing so would require a hit to the database and i am not yet ready to persist the User yet so I do validate it. Meanwhile, I create a new company and persist it. I only want to persist the changes to the user if the additon of the compnay succeeded. But when persisting the company, NHibernate also flushes the changes made to the user. So now I have two users in the database with the same email address.

I know this example makes no logical sense in the reall world. I am just trying show how inconsistent data could occur if there is no way to prevent NHibernate from persisting data that hasnt been validated.

So there just needs to be a way to ensure that an object has been validated before it is persisted.

The IIntercpetor method is really the only option I see at this point.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 9:17 pm 
Regular
Regular

Joined: Mon May 16, 2005 1:35 am
Posts: 67
IMO it is really important to maintain a separation of concerns in your architecture. Although encapsulating validation rules is a concern of the domain layer, persistence should not be.

If your validation logic is based on the "Safeguard" pattern - i.e. you have a "Validate()" method which must be invoked before a domain object is persisted, then IMO it is the responsibility of the code that persists the domain object to invoke the Validate method before persisting the object to ensure the object is safe to persist.

If the domain object has no knowledge of persistence, it should not need to be automatically aware of when it is being persisted.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 11:39 pm 
Senior
Senior

Joined: Sat Sep 03, 2005 12:54 am
Posts: 139
Hmmm...interesting stuff. Thanks for all your replies.

The argument that the domain entities should be completely unaware of the ORM is quite compelling and the use of Lifecycle and Validatable would break that rule. The Interceptor seems better but then again you can't access the session which is a right pain!

The problem as I see it is that the most logical and safest place to call validation is just before an object is persisted to the DB as this always ensures that an object has valid state. Relying on the developer to call a validation method manually is bound to be problematic...you know how unreliable developers are :wink:

So, I guess it is back to my original question, which is how is everyone else doing validaton with NH?

KPixel: you mentioned that you don't use ILifecycle, IValidatable and IInterceptor...how do you do it then? Also, from what I've read, none of these methods are usable anyway as they are either not reliably called by NH or do not have access to the session.

Thanks,

Jason


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 12, 2005 1:46 pm 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
In my last project (a Windows Application), I built the forms so that after the user edit an entity and click on "Save", the entity is updated (the validation is done by the entity while it is updated); if there is any error (throwed exception), the form show the error, else the entity is saved.

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 12, 2005 2:20 pm 
Senior
Senior

Joined: Sat Sep 10, 2005 3:46 pm
Posts: 178
Jason, Im not suggesting that you do your validation with the interceptor.

My suggestion is this.
Have an interface that has a property such as HasBeenValidated or it could even be IsValid but IsValid would not be true unless a developer has actually called Validate. so lets go with HasBeenValidated to be more clear.

Code:
IValidationVerifiable{
   bool HasBeenValidated{get;}
}


Now the interceptor looks for types that implement IValidationVerifiable. If it finds an IValidationVerifiable it checks HasBeenValidated. If the entity has not been validated then it will throw an exception. This prevents developers from being able to persist an entity that hasnt been validated.

The catch here is that you have to make sure that your entity will set HasBeenValidated back to false if it changes a field that requires validation. Thats not to much of a burden though. Or you could just add a property setter to IValidationVerifiable that you could use to have the interceptor mark the entity as requiring validation again after it has been persisted.

How does that sound? Is that a good soluton to your problem of wild devs?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 14, 2005 9:27 am 
Senior
Senior

Joined: Sat Sep 03, 2005 12:54 am
Posts: 139
Hi jnapier,

Your suggestion does seem very workable although I am not overly keen on plumbing the properties with code to flag the object as invalid. However, this is pretty much the same as Fowlers pattern for flagging a domain object as dirty to the UnitOfWork so I guess it must be OK!! I just don't like repetetive coding that can be easily overlooked/fogotten by wild devs :wink:

jnapier wrote:
Or you could just add a property setter to IValidationVerifiable that you could use to have the interceptor mark the entity as requiring validation again after it has been persisted.


Not too sure I fully see how this is going to work. Are you saying that the object would be marked as "requiring validation" just after it is persisted to the DB even though it really doesn't need to be? This method would also require the object to be marked as "requiring validation" OnLoad of the object as well then if I wanted to avoid plumbing the properties. This doesn't quite feel right to me but maybe I'm being overly sensitive!

Is this how you have done validation with NH? Personally, I would have really liked to have access to the session in the Interceptor and then all my problems would be solved! I wonder why this is not possible in NH?

Thanks for taking the time to respond.

Jason


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 17, 2005 11:53 pm 
Newbie

Joined: Sun Oct 16, 2005 4:54 am
Posts: 7
Client /Server

Client:
Data entry validation (some business rule object).
If you want to have a user friendly error feedback you need to send some request to server or local cache to validate current value.

Server:
let database do it job (define field that must be unique)
after persist the data on the client side let catch some exception.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 18, 2005 5:27 pm 
Senior
Senior

Joined: Sat Sep 10, 2005 3:46 pm
Posts: 178
Im not to pumped on having to set the HasBeenValidated from the Interceptor either. I am also not to keen on having to do it in the properties.

Basically my entities are always validated. the only Time they me need to be validated is when it is expensive to validate the property.

So I only set the HasBeenValidated = false when a property has been modified that is expensive to validate. Then Validate must be called on the object. This causes me to only have to set HasBeenValidated to false form expensive properties.

I know its not the greatest but I dont have a better solution either.

I heard that in Hibernate 3 there is full eventing on objects such as OnCommit. That shure would make life easy.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 21 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.