Different validations on same field based on active validation group - spring

I am trying to validate a request object using Hibernate Validator.
As a simple example assume that the class of the object I am trying to validate has a B bObj field where B is another class that has a String name field .
For that reason, I have implemented my own custom Constraint Annotations linked to custom MyValidator implements ConstraintValidator classes.
DTO class
#AclassValidate(groups = {Operations.Insert.class, Operations.Update.class javax.validation.groups.Default.class})
public class A {
#BclassValidate(groups = {Operations.Insert.class, Operations.Update.class})
private B bObj;
// setters, getters
}
My endpoint method signature (where validator gets invoked, and the active group is set):
#PostMapping("/test")
public A createA(
#Validated(value = Operations.Insert.class)
// #Validated(value = Operations.Update.class)
#RequestBody A a
)
My validator class
public class BclassValidator implements ConstraintValidator<BclassValidate, B> {
public void initialize(BclassValidate constraintAnnotation) {
}
public boolean isValid(B b, ConstraintValidatorContext constraintContext) {
boolean valid = true;
// Get active group here
activeGroup = ..?
if (activeGroup == Operations.Insert.class) {
// check if b.getName() equals to "John"
}
else if (activeGroup == Operations.Update.class) {
// check if b.getName() equals to "Doe"
}
return valid;
}
}
What I want to achieve is to apply different validations for the same field based on the active group. The active group is the group, set at #Validated annotation. The question is how can I retrieve the active group in order to apply different validations based on its value?

You cannot get hold of the currently validated group(s) from within a constraint validator.
Instead you should split up your constraint into several ones, in your case one for inserts and one for updates. Then you can assign these individual constraints to one validation group each.

You should get the active validation groups like this:
public class BclassValidator implements ConstraintValidator<BclassValidate, B> {
public void initialize(BclassValidate constraintAnnotation) {
}
public boolean isValid(B b, ConstraintValidatorContext constraintContext) {
boolean valid = true;
// Get active group here
Set<Class<?>> activeGroups = null;
if (context instanceof ConstraintValidatorContextImpl) {
activeGroups = ((ConstraintValidatorContextImpl) context).getConstraintDescriptor().getGroups();
} else {
activeGroups = Collections.emptySet();
}
if (activeGroups.contains(Operations.Insert.class)) {
// check if b.getName() equals to "John"
}
else if (activeGroups.contains(Operations.Update.class)) {
// check if b.getName() equals to "Doe"
}
return valid;
}
}

Hibernate validator validating the currently active groups with the configured groups for custom constraints, so we no need to write logic to validate it. But there is no way to find the currently active groups.
Reason: 'valueContext' is holding the currently active group, but not passing to 'isValid' method.
https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java

Related

Hotchocolate, turn on/off sorting by field in a type

I expose my 'Example' class using IQueryable and apply the [UseSorting] attribute so the user can define the sort order of the results. This works fine and the Playground allows me to do exactly that.
public class QueryType : ObjectType
{
[UseSorting]
public IQueryable<Example> GetExamples([Service]IExampleRepository repository)
{
return repository.GetExamples();
}
}
public class ExampleType : ObjectType<Example>
{
protected override void Configure(IObjectTypeDescriptor<Example> descriptor)
{
}
}
But the 'Example' class has three properties and I only want 2 of them to be orderable by the user. It makes no sense for the user to order by the third property. How do you specify one of the properties of 'Example' to be excluded from the ordering middleware?
Suppose, you have Prop1, Prop2 and Prop3 and want to allow only sorting Prop1 and Prop2. To reach that you just need to implement the "sorting metadata" type in the following way:
public class ExampleSortType : SortInputType<Example>
{
protected override void Configure(ISortInputTypeDescriptor<Example> descriptor)
{
ISortInputTypeDescriptor<Example> sortInputTypeDescriptor = descriptor.BindFieldsExplicitly();
sortInputTypeDescriptor.Sortable(d => d.Prop1);
sortInputTypeDescriptor.Sortable(d => d.Prop2);
}
}
and provide the UseSorting attribute with that metadata type:
[UseSorting(SortType = typeof(ExampleSortType))]
public IQueryable<Example> GetExamples([Service]IExampleRepository repository)...

Cross field validation based on value

If we are build a custom JSR 303 validator, is there any way, we can pass field's value to the validator instead of the field's name?
Here is what I am doing..
I need to build a custom class level validation which validates this case..
There are two fields A & B where B is a date field. If A's value is 1, verify that B is not null and its value is future date.
Now I was able to build a validation with these requirements following this post. In the FutureDateValidator's isValid() method, I have checked whether A's value is 1 or not and then I checked the date validity.
#CustomFutureDate(first = "dateOption", second = "date", message = "This must be a future date.")
Now I have new set of fields C and D, where D is again the date field. This time I need to verify that D is a future date if C's value is 2. In this case I cannot use the validator I already implemented because it has the first field's value hard-coded. So how do I solve this issue to reuse the same validator for these two cases.
To not hardcode values 1/2 made it customizable:
#CustomFutureDate(first = "dateOption", firstValue = "1", second = "date", message = "This must be a future date.")
To make it work you need to modify #CustomFutureDate annotation:
public #interface CustomFutureDate {
String first();
String firstValue();
...
}
and implementation:
public class CustomFutureDateValidator implements ConstraintValidator<CustomFutureDate, Object> {
private String firstFieldName;
private String firstFieldValue;
...
#Override
public void initialize(final CustomFutureDate constraintAnnotation) {
firstFieldName = constraintAnnotation.first();
firstFieldValue = constraintAnnotation.firstValue();
...
}
#Override
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
// use firstFieldValue member
...
}
}

Is there a way to disable Castle Active Record validation for an nhibernate session / active record scope

Is there a way to disable Active Record validation for an nhibernate session / active record scope?
I have a scenario whereby we are performing deletion of a large number of items - and in some cases customers have data in their database that will not pass validation (it was captured prior to new validation rules being introduced, or due to manual manipulation of the database etc.)
When deleting, due the way the database is constructed, some validation checks on existing entities occur, and fail with an exception - preventing the deletion of those entities.
For the deletion scenario we would like to disable all validation from occurring associated with the transaction/session/scope the entities are being deleted within, is this possible?
Update 23/01/2011
Implemented a simple validation active record base class for disabling validation:
public class DisabledValidationProvider : IValidationProvider
{
public bool IsValid()
{
return true;
}
public bool IsValid(RunWhen runWhen)
{
return true;
}
public string[] ValidationErrorMessages
{
get { return null; }
}
public IDictionary PropertiesValidationErrorMessages
{
get { return null; }
}
}
public class DisableValidationScope : IDisposable
{
public DisableValidationScope()
{
Local.Data["DisableValidationScope"] = true;
}
public static bool IsValidationDisabled
{
get { return Local.Data["DisableValidationScope"] != null; }
}
public void Dispose()
{
Local.Data["DisableValidationScope"] = null;
}
}
public abstract class ScopeAwareValidationBase : ActiveRecordHooksValidationBase
{
static readonly IValidationProvider DisabledProvider = new DisabledValidationProvider();
protected override IValidationProvider ActualValidator
{
get
{
if (DisableValidationScope.IsValidationDisabled)
{
return DisabledProvider;
}
return base.ActualValidator;
}
}
}
My ActiveRecord models inherit from ScopeAwareValidationBase and then I can just emplot a using statement around my transaction code, works a treat.
using (new DisableValidationScope())
{
// do transactional thing...
}
I'd look into overriding the ActualValidator property, there you could either:
provide a setter, to let your code decide whether to apply validation or not on a per-instance basis, or
(better) look up some context associated to the current SessionScope that decides whether to apply validation or not.
To disable validation, you'd return a dummy IValidationProvider that always returned true to IsValid(), etc.

Validating a domain object for persistence

In the system I'm currently working on, I'm following SRP (I think!) by separating the validation of domain business rules vs persistence constraints. Let's employ the overused customer example. Say a customer must have a valid zip code, street address and name to satisfy the system's business rules. Let's further say that the customer's selected user name must be unique across all customers, which I define as a persistence constraint. Please consider the following "not ready for production" pseudo code:
public interface IPersistenceValidator<T>
{
bool IsValidForPersistence(T domainObj, IList<ValidationError> validationErrors);
}
public interface IValidatable
{
bool IsValid(IList<ValidationError> validationErrors);
}
public class Customer : IValidatable
{
public bool IsValid(IList<ValidationError> validationErrors)
{
//check for business rule compliance
}
}
public class CustomerDao : IPersistenceValidator<Customer>
{
public bool IsValidForPersistence(Customer domainObj, IList<ValidationError> validationErrors)
{
//check for persistence constraint compliance (user name is unique)
}
public bool SaveCustomer(Customer customer)
{
//save customer
}
}
The classes defined above might get wired up into a service class as follows:
public class SaveCustomerService
{
private CustomerDao _customerDao;
public SaveCustomerService(CustomerDao customerDao)
{
_customerDao = customerDao;
}
public bool SaveCustomer(Customer customer)
{
IList<ValidationError> validationErrors = new List<ValidationError>();
if (customer.IsValid(validationErrors))
{
if (_customerDao.IsValidForPersistence(customer, validationErrors))
{
return _customerDao.SaveCustomer(customer);
}
else
{
return false;
}
}
else
{
return false;
}
}
}
My primary concern with this approach is that future consumers of CustomerDao must know to call IsValidForPersistence() before SaveCustomer(), otherwise invalid data gets persisted. I could create DB constraints to guard against this at the SQL levels, but that feels like a kludge.
It seems like IsValidForPersistence() should be moved into CustomerDao.SaveCustomer() but then I have to refactor the signature of SaveCustomer() to include references to the ValidationErrors class. Before I dive into that big of a refactoring, I wanted to get some feedback from others on common/preffered patterns for dealing with these issues.
Thanks
first check HERE if you want to solve your validation problem like;
public class Address {
#NotNull private String line1;
private String line2;
private String zip;
private String state;
#Length(max = 20)
#NotNull
private String country;
#Range(min = -2, max = 50, message = "Floor out of range")
public int floor;
...
}
anyway you must check username in database. You can customize your validation (like go and check DB for that is unique). Look at another links to detail.
Check hibernate validator
Check Using the Validator framework from jboss
You can read Validation In The Domain Layer partI, partII, this is not java but logic is important.

Validation in a Domain Driven Design

How do you deal with validation on complex aggregates in a domain driven design? Are you consolidating your business rules/validation logic?
I understand argument validation and I understand property validation which can be attached to the models themselves and do things like check that an email address or zipcode is valid or that a first name has a minimum and maximum length.
But what about complex validation that involves multiple models? Where do you typically place these rules & methods within your architecture? And what patterns if any do you use to implement them?
Instead of relying on IsValid(xx) calls all over your application, consider taking some advice from Greg Young:
Don't ever let your entities get into
an invalid state.
What this basically means is that you transition from thinking of entities as pure data containers and more about objects with behaviors.
Consider the example of a person's address:
person.Address = "123 my street";
person.City = "Houston";
person.State = "TX";
person.Zip = 12345;
Between any of those calls your entity is invalid (because you would have properties that don't agree with each other. Now consider this:
person.ChangeAddress(.......);
all of the calls relating to the behavior of changing an address are now an atomic unit. Your entity is never invalid here.
If you take this idea of modeling behaviors rather than state, then you can reach a model that doesn't allow invalid entities.
For a good discussion on this, check out this infoq interview: http://www.infoq.com/interviews/greg-young-ddd
I like Jimmy Bogard's solution to this problem. He has a post on his blog titled "Entity validation with visitors and extension methods" in which he presents a very elegant approach to entity validation that suggest the implementation of a separate class to store validation code.
public interface IValidator<T>
{
bool IsValid(T entity);
IEnumerable<string> BrokenRules(T entity);
}
public class OrderPersistenceValidator : IValidator<Order>
{
public bool IsValid(Order entity)
{
return BrokenRules(entity).Count() == 0;
}
public IEnumerable<string> BrokenRules(Order entity)
{
if (entity.Id < 0)
yield return "Id cannot be less than 0.";
if (string.IsNullOrEmpty(entity.Customer))
yield return "Must include a customer.";
yield break;
}
}
I usualy use a specification class,
it provides a method (this is C# but you can translate it in any language) :
bool IsVerifiedBy(TEntity candidate)
This method performs a complete check of the candidate and its relations.
You can use arguments in the specification class to make it parametrized, like a check level...
You can also add a method to know why the candidate did not verify the specification :
IEnumerable<string> BrokenRules(TEntity canditate)
You can simply decide to implement the first method like this :
bool IsVerifiedBy(TEntity candidate)
{
return BrokenRules(candidate).IsEmpty();
}
For broken rules, I usualy write an iterator :
IEnumerable<string> BrokenRules(TEntity candidate)
{
if (someComplexCondition)
yield return "Message describing cleary what is wrong...";
if (someOtherCondition)
yield return
string.Format("The amount should not be {0} when the state is {1}",
amount, state);
}
For localization, you should use resources, and why not pass a culture to the BrokenRules method.
I place this classes in the model namespace with names that suggest their use.
Multiple model validation should be going through your aggregate root. If you have to validate across aggregate roots, you probably have a design flaw.
The way I do validation for aggregates is to return a response interface that tells me if validation pass/fail and any messages about why it failed.
You can validate all the sub-models on the aggregate root so they remain consistent.
// Command Response class to return from public methods that change your model
public interface ICommandResponse
{
CommandResult Result { get; }
IEnumerable<string> Messages { get; }
}
// The result options
public enum CommandResult
{
Success = 0,
Fail = 1
}
// My default implementation
public class CommandResponse : ICommandResponse
{
public CommandResponse(CommandResult result)
{
Result = result;
}
public CommandResponse(CommandResult result, params string[] messages) : this(result)
{
Messages = messages;
}
public CommandResponse(CommandResult result, IEnumerable<string> messages) : this(result)
{
Messages = messages;
}
public CommandResult Result { get; private set; }
public IEnumerable<string> Messages { get; private set; }
}
// usage
public class SomeAggregateRoot
{
public string SomeProperty { get; private set; }
public ICommandResponse ChangeSomeProperty(string newProperty)
{
if(newProperty == null)
{
return new CommandResponse(CommandResult.Fail, "Some property cannot be changed to null");
}
SomeProperty = newProperty;
return new CommandResponse(CommandResult.Success);
}
}
This questions a bit old now but in case anyone is interested here's how I implement validation in my service classes.
I have a private Validate method in each of my service classes that takes an entity instance and action being performed, if validation fails a custom exception is thrown with the details of the broken rules.
Example DocumentService with built in validation
public class DocumentService : IDocumentService
{
private IRepository<Document> _documentRepository;
public DocumentService(IRepository<Document> documentRepository)
{
_documentRepository = documentRepository;
}
public void Create(Document document)
{
Validate(document, Action.Create);
document.CreatedDate = DateTime.Now;
_documentRepository.Create(document);
}
public void Update(Document document)
{
Validate(document, Action.Update);
_documentRepository.Update(document);
}
public void Delete(int id)
{
Validate(_documentRepository.GetById(id), Action.Delete);
_documentRepository.Delete(id);
}
public IList<Document> GetAll()
{
return _documentRepository
.GetAll()
.OrderByDescending(x => x.PublishDate)
.ToList();
}
public int GetAllCount()
{
return _documentRepository
.GetAll()
.Count();
}
public Document GetById(int id)
{
return _documentRepository.GetById(id);
}
// validation
private void Validate(Document document, Action action)
{
var brokenRules = new List<string>();
if (action == Action.Create || action == Action.Update)
{
if (string.IsNullOrWhiteSpace(document.Title))
brokenRules.Add("Title is required");
if (document.PublishDate == null)
brokenRules.Add("Publish Date is required");
}
if (brokenRules.Any())
throw new EntityException(string.Join("\r\n", brokenRules));
}
private enum Action
{
Create,
Update,
Delete
}
}
I like this approach because it allows me to put all my core validation logic in one place which keeps things simple.

Resources