Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 10 posts ] 
Author Message
 Post subject: New Features
PostPosted: Sat Jan 31, 2009 8:37 am 
Newbie

Joined: Sat Jan 31, 2009 6:26 am
Posts: 4
Location: Novi Sad Serbia
Hello,
Before 2 years I made validation system for my company very similar to JSR 303.
Actually concept is completely same; differences are in validation annotation names and it not support grouping validation (groups).
Company is very satisfied with it, so it is not changed until now.

When I saw JSR 303 I was very happy and satisfied with it.
I have some recommendations and features which could be supported and which is used in our validation system:

1. Valid annotation (my DeepValidation) could have group/groups like others annotations.
This could be useful if we want to deep validate in some cases and not in other.
My annotation has deep level property but this feature is not use and it is probably necessary.

2. Some annotations have reportOn property like NotEmpty.
This is used for reporting constraint on another property.
Ex.:
class UsrContact {

@NotEmpty(reportOn="email.address")
private Email email;
}

class Email {
private Address address;
private Address secondAddr;
...
}
This is needed because UI presentation. Email field not exist on UI, instead email.address field is displayed.
When all fields from Email are empty email object is null.
@NotEmpty will report constraint on email property and this error couldn’t be displayed.

3. Some constraint validators could use additional interfaces for its check.
Ex. NotEmpty validator could use Empty interface for its checking.

interface Empty {
boolean isEmpty();
}
Empty checking could be complicated for some classes and instead of complicating constraint validator
validating object could provide method how to do that.


class Localization implements Empty {
Map<Locale,LocalizationFields> loc;
...
boolean public isEmpty() {
return loc.isEmpty();
}
}

public boolean isValid(Object value, ConstraintContext constraintContext) {
...
if ( value instanceof Empty )
return ((Empty)value).isEmpty();
...
}


4. I think it could be useful to create group/groups annotation on type level.
Sometimes one Type could use always the same groups during validation.

Instead of providing appropriate group for each object during validation
Validator.validate(T object, Class<?>... groups);

validator could check does validating object (type) has some groups and use it during validation process.

Thanks,
Nenad


Top
 Profile  
 
 Post subject: Re: New Features
PostPosted: Mon Feb 02, 2009 3:14 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Hi thanks for your feedback.

nvico wrote:
Hello,
1. Valid annotation (my DeepValidation) could have group/groups like others annotations.
This could be useful if we want to deep validate in some cases and not in other.
My annotation has deep level property but this feature is not use and it is probably necessary.

hum interesting. Today this can be done:
- via a custom TraversableResolver I suppose but not easily.
- by adding the DeepValidation group to the associated objects constraints

How useful was this feature at your company?

My problem with that is that @Valid would be used only when Default is validated by default. and I find that a bit dangerous.


Quote:

2. Some annotations have reportOn property like NotEmpty.
This is used for reporting constraint on another property.
Ex.:
class UsrContact {

@NotEmpty(reportOn="email.address")
private Email email;
}

class Email {
private Address address;
private Address secondAddr;
...
}
This is needed because UI presentation. Email field not exist on UI, instead email.address field is displayed.
When all fields from Email are empty email object is null.
@NotEmpty will report constraint on email property and this error couldn’t be displayed.


You can do that:
The ConstraintValidator implementation accepts a constraintValidatorContext object which can addError(String emssage, String property). Today it raises an exception if this method is used on a property (as opposed to a Bean-level constraint), but that's a good use case to relax that.
reportOn would not be "standard" but you could add it then to your own constraints

Quote:
3. Some constraint validators could use additional interfaces for its check.
Ex. NotEmpty validator could use Empty interface for its checking.

interface Empty {
boolean isEmpty();
}
Empty checking could be complicated for some classes and instead of complicating constraint validator
validating object could provide method how to do that.


class Localization implements Empty {
Map<Locale,LocalizationFields> loc;
...
boolean public isEmpty() {
return loc.isEmpty();
}
}

public boolean isValid(Object value, ConstraintContext constraintContext) {
...
if ( value instanceof Empty )
return ((Empty)value).isEmpty();
...
}


I hate that :)
That being said, you can easily implement that on top of Bean Validation out of the box, you just define your own interfaces.

Quote:
4. I think it could be useful to create group/groups annotation on type level.
Sometimes one Type could use always the same groups during validation.

Instead of providing appropriate group for each object during validation
Validator.validate(T object, Class<?>... groups);

validator could check does validating object (type) has some groups and use it during validation process.


If a given type (Address) must always been validated using a given group (ValidAddress), why not tag constraints with the Default group instead?

Also note that you can place a @GroupSequence on a class to define some kind of group sequencing replacing the Default group for a given class.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 02, 2009 7:07 am 
Newbie

Joined: Sat Jan 31, 2009 6:26 am
Posts: 4
Location: Novi Sad Serbia
Hi Emmanuel,

Thanks for explanations.

emmanuel wrote:
hum interesting. Today this can be done:
- via a custom TraversableResolver I suppose but not easily.
- by adding the DeepValidation group to the associated objects constraints

How useful was this feature at your company?

My problem with that is that @Valid would be used only when Default is validated by default. and I find that a bit dangerous.



I thought that @Valid is replacement for DeepValidation

DeepValidation is main feature of validation system and it is very powerful.
Actually we have to define validation only once per Type and by declaring DeepValidation we use the same logic in any composite Type.
There is no horrible repeating of same logic for validating child objects.

In my opinion DeepValidation group in associated objects constraints is not consistent
Ex:
Code:
class Email {
   
    @Email
    @Size(max=100)
    private String address;
    private int modifyBy;
    ....
}

@NotEmpty(group=DeepValidation)
private Email email;


DeepValidation should check all constraints of Email type, not only NotEmpty check, something like @Valid

As I mention above we are not using concept of groups which is very powerfully.
Instead of that we are using DeepValidation + children property for each Constraint.

We have case where Email is required in some composite and not in another.
The worst case is Client where we have 2 emails one is required and one is not.
We resolve this on next way:
Code:
class Contact {
    ...
    @DeepValidation
    private Email email;
    ...
}

class Client {
    ...
    @NotEmpty(children="address",itself=true, reportOn="prim.address")
    @DeepValidation
    private Email prim;

    @DeepValidation
    private Email second;
    ...
}


Actually Email is used in lot of Types and this number always grow,
so we can't change Email type when we want to add it somewhere. (add new groups,... )

Is it possible to resolve this by current JSR 303 somehow?

In our experience Validation by annotation speed up validation development process 2 times and DeepValidation multiply it by 3

Thanks,
Nenad
Code:
Code:


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 02, 2009 1:16 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
I am afraid "deep validation" is still a bit confusing to me.
Can you jsut describe the usecase you are looking to cover and I will see if BV fits it. Remember I don't know your validation framework :)

class Customer {
@Valid @NotNull Email email;
}

will validate that the email object is not null and that all its properties are valid (ie validate the constraints of the default group, if the default group is requested).

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 02, 2009 5:14 pm 
Newbie

Joined: Sat Jan 31, 2009 6:26 am
Posts: 4
Location: Novi Sad Serbia
Hi Emmanuel,

I will try to simplify usecase as possible and I can't use real one because of company privacy.
Code:
public class Email {

    private long id;
   @Email
    @Size(max=100)
    private String address;
   ...
}

Email type has Email and Size constraints. NotEmpty is not used because email could be optional.

Code:
public class Client implements Validatable {

    @NotEmpty(children="address", reportOn="primary.address")
    @DeepValidation
    private Email primary;

    @DeepValidation
    private Email secondary;
   
   /**
    * Custom validation logic.
    */
    // Our solution don't have this parameters
   public void validate(ConstraintContext constraintContext, Class<?>... groups) {
      ...
   }
}


Client contains primary email and secondary email, primary is required (NotEmpty) and secondary is optional.

Client validation validator.validate(client);
should check constraints:
1. @Email, @Size and @NotEmpty against primary property and report error on primary.address field.
2. @Email and @Size against secondary property and report error on secondary.address field.
3. check business custom validation which can't be automated by annotation. Our solution don't have this parameter

Code:
public class Contact {

   @DeepValidation
    private Email email;
   
   @DeepValidation
    private Address address;
   ...   
}

Contact validation should check constraints:
1. @Email and @Size against email property and report error on email.address field.
2. check other fields

Code:
public class User implements Validatable {

   private long id;
   
   @NotEmpty(children="contact.email.address",reportOn="contact.email.address")
   @DeepValidation
   private Contact contact;
   ...
   
   public void validate(ConstraintContext constraintContext, Class<?>... groups) {
      ...
   }
}


User validation should check constraints:
1. repeat whole validation logic on Contact type and report error on Contact fields plus contact prefix (Ex. contact.address)
2. @NotEmpty against contact.email.address property.
2. check other fields
3. check business custom validation which can't be automated by annotation.

Code:
public class Group implements Validatable {
   
   @DeepValidation
   private List<Contact> contacts;
   ...
}


Group validation should check constraints:
1. repeat whole validation logic on Contact type for each contacts object and report error on Contact fields plus contacts[index] prefix
(Ex. contacts[2].email.address)
2. check other fields
3. check business custom validation which can't be automated by annotation.

DeepValidation used to define repetition of whole validation of child object type in composite type.
Without that, composite object validation will become nightmare where we have to repeat whole validation logic of child object
with only one difference in additional prefix.

I am not happy with children property in Constraint because I have to know structure of child object.
I rudder prefer validation grouping and use something like:

Code:
public class Email {

    private long id;
   @Email
    @Size(max=100)
   @NotEmpty(group="required")
    private String address;
   ...
}

public class Client implements Validatable {

    @DeepValidation(childrenGroup="required")
    private Email primary;

    @DeepValidation
    private Email secondary;
   ...
}


Thanks,
Nenad


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 13, 2009 9:14 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
I looked at all your use cases and @Valid + groups cover them.
(except the Validatable interface but I am not convinced it can't be done via a class level constraint already).

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 16, 2009 10:39 am 
Newbie

Joined: Sat Jan 31, 2009 6:26 am
Posts: 4
Location: Novi Sad Serbia
Thank you Emmanuel,

Emmanuel wrote:

I looked at all your use cases and @Valid + groups cover them.
(except the Validatable interface but I am not convinced it can't be done via a class level constraint already).


Validatable interface is one implementation of custom validation that is not important.

I try to figure out how to resolve problem with primary and secondary email address by using groups and @Valid
but I didn't catch it from spec :(

Actually I don't know how to distinct that secondary email allows empty value and primary not in Client.class

Thanks,
Nenad


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 16, 2009 11:39 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
ah yes, I got it now, this use case is not well covered unless you ask the validate client to use explicit groups :(

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 16, 2009 11:41 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
@Valid(groups=...) might be a solution but I am not very comfortable to introduce this feature in this version.

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Re: New Features
PostPosted: Tue Mar 25, 2014 7:56 am 
Newbie

Joined: Mon Dec 09, 2013 2:23 am
Posts: 6
Really thankful to you for the informative post with the new validation system you have prepared. If you can share how these new software works, it would be very helpful for everyone to implement the same and make use of this.





CORBIN


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

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.