play framework validation binding invalid input value with POJO - validation

I have a model TestModel.java which contains a field declared like below
#Required
#IntegerAnnotation
#Column (length = 4, nullable = false)
public Integer sort;
For the default validation annotation of Play doesn't support Integer check, so I create an annotation validation for checking the input value is an Integer or not.
The IntegerAnnotation.java :
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.PARAMETER})
#Constraint(checkWith = IntegerCheck.class)
public #interface IntegerAnnotation {
String message() default IntegerCheck.message;}
}
and this annotation refers to an implementations of IntegerCheck.java
public class IntegerCheck extends AbstractAnnotationCheck<IntegerAnnotation>{
final static String message = "validation.integer";
#Override
public boolean isSatisfied(Object validatedObject, Object value, OValContext context, Validator validator) throws OValException {
// TODO Auto-generated method stub
if(value == null) return false;
return isInteger(value.toString());
}
private static boolean isInteger(String s) {
return isInteger(s,10);
}
private static boolean isInteger(String s, int radix) {
if(s.isEmpty()) return false;
for(int i = 0; i < s.length(); i++) {
if(i == 0 && s.charAt(i) == '-') {
if(s.length() == 1) return false;
else continue;
}
if(Character.digit(s.charAt(i), radix) < 0) return false;
}
return true;
}
}
And there are two actions in the controller for create or update the TestModel, method create and method update.
public static void create(#Valid TestModel testModel){
if(validation.hasErrors()) {
params.flash();
validation.keep();
blank();
}
}
public static void update(#Valid TestModel testModel) {
if(validation.hasErrors()) {
params.flash();
validation.keep();
}
else{
testModel.save();
show(sys5000.id);
}
}
I found when the field sort is not entered with integer value, the value will be null in the create method, that's why I put a if null condition in the IntegerCheck.class.
Thus, if the value of filed sort is wrong typed, it detects null and return false.
Though it's not what I expect it will use the wrong typed value to verify, it worked...sort of.
The problem is in the update method.
For when updating an instance of TestModel, it won't show the wrong typed value, but the original retrieved value from database instead.
It's really a problem, for it will always return true if the retrieved data from database is already an integer. Then the validation won't do the work.
And the questions are:
Any advice for this validation strategy? I think maybe I'm apart from the right way to verify the Integer value validation.
How can I retrieve the wrong typed value from the action, or it's just not possible, for it's already not a valid data type of that field.

The behavior that you see in the update method is the way Play works!
Here is the relevant section from the documentation :
... When Play finds the id field, it loads the matching instance from
the database before editing it. The other parameters provided by the
HTTP request are then applied.
So in your case, when the sort property is null during an update, the value in the database is used.
Now if I were to try to achieve what you are trying to do, I would propably do it this way :
In my model
#Required
#CheckWith(IntegerCheck.class)
public int sort; // using primitive here to avoid null values.
static class IntegerCheck extends Check {
public boolean isSatisfied(Object model, Object sort) {
int fieldValue = (int) sort; // here you have the value as int
// Here you would check whatever you want and return true or false.
return ...
}
}

Related

Sort a list of objects based on a parameterized attribute of the object

Assuming that we have an object with the following attributes:
public class MyObject {
private String attr1;
private Integer attr2;
//...
public String getAttr1() {
return this.attr1;
}
public Integer getAttr2() {
return this.attr2;
}
}
One way of sorting a list mylist of this object, based on its attribute attr1 is:
mylist.sort(Comparator.comparing(MyObject::getAttr1));
Is it possible to use this code inside a method in a dynamic way and replace the getAttr1 part with a method that returns the getter of an attribute of the object based on its name? Something like:
public void sortListByAttr(List<MyObject> list, String attr) {
list.sort(Comparator.comparing(MyObject::getGetterByAttr(attr)));
}
The MyObject::getGetterByAttr(attr) part does not compile, I wrote it just as an example to explain my idea
I tried to implement a method with the following code new PropertyDescriptor(attr, MyObject.class).getReadMethod().invoke(new MyObject()) but It's still not possible to call a method with a parameter from the comparing method
You could add a method like
public static Function<MyObject,Object> getGetterByAttr(String s) {
switch(s) {
case "attr1": return MyObject::getAttr1;
case "attr2": return MyObject::getAttr2;
}
throw new IllegalArgumentException(s);
}
to your class, but the returned function is not suitable for Comparator.comparing, as it expects a type fulfilling U extends Comparable<? super U> and while each of String and Integer is capable of fulfilling this constraint in an individual invocation, there is no way to declare a generic return type for getGetterByAttr to allow both type and be still compatible with the declaration of comparing.
An alternative would be a factory for complete Comparators.
public static Comparator<MyObject> getComparator(String s) {
switch(s) {
case "attr1": return Comparator.comparing(MyObject::getAttr1);
case "attr2": return Comparator.comparing(MyObject::getAttr2);
}
throw new IllegalArgumentException(s);
}
to be used like
public void sortListByAttr(List<MyObject> list, String attr) {
list.sort(getComparator(attr));
}
This has the advantage that it also may support properties whose type is not Comparable and requires a custom Comparator. Also, more efficient comparators for primitive types (e.g. using comparingInt) would be possible.
You may also consider using a Map instead of switch:
private static Map<String,Comparator<MyObject>> COMPARATORS;
static {
Map<String,Comparator<MyObject>> comparators=new HashMap<>();
comparators.put("attr1", Comparator.comparing(MyObject::getAttr1));
comparators.put("attr2", Comparator.comparing(MyObject::getAttr2));
COMPARATORS = Collections.unmodifiableMap(comparators);
}
public static Comparator<MyObject> getComparator(String s) {
Comparator<MyObject> comparator = COMPARATORS.get(s);
if(comparator != null) return comparator;
throw new IllegalArgumentException(s);
}
More dynamic is only possible via Reflection, but this would complicate the code, add a lot of potential error source, with only little benefit, considering that you need only to add one line of source code for adding support for another property in either of the examples above. After all, the set of defined properties gets fixed at compile time.
You could also have a single place where this comparators would be defined:
static enum MyObjectComparator {
ATTR1("attr1", Comparator.comparing(MyObject::getAttr1));
MyObjectComparator(String attrName, Comparator<MyObject> comparator) {
this.comparator = comparator;
this.attrName = attrName;
}
private final Comparator<MyObject> comparator;
private final String attrName;
private static MyObjectComparator[] allValues = MyObjectComparator.values();
public static Comparator<MyObject> findByValue(String value) {
return Arrays.stream(allValues)
.filter(x -> x.attrName.equalsIgnoreCase(value))
.map(x -> x.comparator)
.findAny()
.orElseThrow(RuntimeException::new);
}
}
And your usage would be:
public void sortListByAttr(List<MyObject> list, String attr) {
list.sort(MyObjectComparator.findByValue(attr));
}

Different validations on same field based on active validation group

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

How and Where to tell if a ViewComponent has been invoked x times in a view?

I have a ViewComponent that I need to invoke twice only! How and where can I tell the invokations count?
Currently I can use a session but I dislike using session in mvc apps! How may I achieve this?
namespace Partials.Components
{
public class MyComponent : ViewComponent
{
public IViewComponentResult Invoke()
{
Session["invoked"]=(int)Session["invoked"]+1;
var model = new{
Website="Stack Overflow",
Url="www.http://stackoverflow.com"
};
return View("_MyComponent ", model);
}
}
}
and in my view
#Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>#Session["invoked"]</span> times</span>
You can use TempData. It persists only until the next request.
TempData["invoked"]=(int)TempData["invoked"]+1;
View:
<span>Invoked ViewComponent <span>#TempData["invoked"]</span> times</span>
Note: TempData uses session under the covers.
You can use HttpContext.Items which has the advantage of not using the session. These items are stored and shared per request, which would also fit your objective.
In your viewComponent you can add/retrieve an item as in this.Context.Items["MyComponentInvocationCount"]. Whenever the count is greater than 2 you can just return an empty content with return Content(String.Empty).
You can combine that with an extension method so you can get the count from outside that class:
[ViewComponent(Name = "MyComponent")]
public class MyViewComponent : ViewComponent
{
internal static readonly string ContextItemName = "InvocationCount";
public IViewComponentResult Invoke()
{
this.InvocationCount = this.InvocationCount + 1;
if (this.InvocationCount > 2) return Content(String.Empty);
//return your content here
return Content("Can be invoked");
}
private int InvocationCount
{
get
{
return this.Context.InvocationCount();
}
set
{
this.Context.Items[ContextItemName] = value;
}
}
}
public static class MyViewComponentExtensions
{
public static int InvocationCount(this HttpContext context)
{
var count = context.Items[MyViewComponent.ContextItemName];
return count == null ? 0 : (int)count;
}
}
Then you could use it in a view as follows:
#Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>#Context.InvocationCount()</span> times</span>
If you add the above lines 3 times in a view, you will see that the third one does not add any content.
EDIT - Using ViewComponentInvoker
I have been exploring how to implement this feature adding a custom ViewComponentInvoker.
I started by adding a new attribute that can be used to decorate ViewComponents so they are limited to a certain number of invocations per request:
public class PerRequestInvocationLimitAttribute: Attribute
{
public int PerRequestInvocationLimit { get; set; }
}
You would then create your view component as usual, the only change being adding this attribute:
[PerRequestInvocationLimit(PerRequestInvocationLimit = 2)]
public class MyViewComponent : ViewComponent
{
//implementation of view component
}
We can then create a custom IViewComponentInvoker that decorates the DefaultViewComponentInvoker.
This custom view component invoker will keep track of the number of
times a view component has been invoked in the current request.
When a view component that has the new attribute is invoked, it will only
really invoke it if the number of invocations is below the limit.
Implementing this view component invoker looks like:
public class LimitedPerRequestViewComponentInvoker : IViewComponentInvoker
{
private readonly IViewComponentInvoker _defaultViewComponentInvoker;
public LimitedPerRequestViewComponentInvoker(IViewComponentInvoker defaultViewComponentInvoker)
{
this._defaultViewComponentInvoker = defaultViewComponentInvoker;
}
public void Invoke(ViewComponentContext context)
{
if (!CanInvokeViewComponent(context)) return;
this._defaultViewComponentInvoker.Invoke(context);
}
public Task InvokeAsync(ViewComponentContext context)
{
if (!CanInvokeViewComponent(context)) return Task.WhenAll();
return this._defaultViewComponentInvoker.InvokeAsync(context);
}
private bool CanInvokeViewComponent(ViewComponentContext context)
{
// 1. Increase invocation count
var increasedCount = context.ViewContext.HttpContext.IncreaseInvocationCount(
context.ViewComponentDescriptor.ShortName);
// 2. check if there is any limit for this viewComponent, if over the limit then return false
var limitAttribute = context.ViewComponentDescriptor.Type
.GetCustomAttributes(true)
.OfType<PerRequestInvocationLimitAttribute>()
.FirstOrDefault();
if (limitAttribute != null && limitAttribute.PerRequestInvocationLimit < increasedCount)
{
return false;
}
// 3. There is no limit set or the limit has not been reached yet
return true;
}
}
It uses some extension methods to set/get the invocation count from HttpContext.Items (That you could also use in your view to get the number of times a view component was invoked)
public static class ViewComponentExtensions
{
public static int InvocationCount(this HttpContext context, string viewComponentName)
{
var count = context.Items[GetHttpContextItemsName(viewComponentName)];
return count == null ? 0 : (int)count;
}
internal static int IncreaseInvocationCount(this HttpContext context, string viewComponentName)
{
var count = context.InvocationCount(viewComponentName);
context.Items[GetHttpContextItemsName(viewComponentName)] = ++count;
return count;
}
private static string GetHttpContextItemsName(string viewComponentName)
{
return string.Format("InvocationCount-{0}", viewComponentName);
}
}
The final piece is to create a new IViewComponentInvokerFactory replacing the default one, so it creates an instance of the new custom view component invoker instead of the default one. You also need to register it on Startup.cs:
public class MyViewComponentInvokerFactory : IViewComponentInvokerFactory
{
private readonly IServiceProvider _serviceProvider;
private readonly ITypeActivatorCache _typeActivatorCache;
private readonly IViewComponentActivator _viewComponentActivator;
public MyViewComponentInvokerFactory(IServiceProvider serviceProvider, ITypeActivatorCache typeActivatorCache, IViewComponentActivator viewComponentActivator)
{
_serviceProvider = serviceProvider;
_typeActivatorCache = typeActivatorCache;
_viewComponentActivator = viewComponentActivator;
}
public IViewComponentInvoker CreateInstance(ViewComponentDescriptor viewComponentDescriptor, object[] args)
{
return new LimitedPerRequestViewComponentInvoker(
new DefaultViewComponentInvoker(_serviceProvider, _typeActivatorCache, _viewComponentActivator));
}
}
//Configure the ViewComponentInvokerFactory in Startup.ConfigureServices
services.AddTransient<IViewComponentInvokerFactory, MyViewComponentInvokerFactory>();
With all these pieces in place, you can use your view component 3 times and you will see how it will be rendered only twice:
#Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>#Context.InvocationCount("MyComponent")</span> times</span>
I prefer this solution for a few reasons:
It is based on the hooks provided by the new mvc framework.
Does not need changes to your view component, other than adding the attribute that sets the invocation limit.
It works when invoking view component asynchronously.

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
...
}
}

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