Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make use of Java type information on annotated fields #24

Closed
bjorndown opened this issue Dec 18, 2014 · 9 comments
Closed

Make use of Java type information on annotated fields #24

bjorndown opened this issue Dec 18, 2014 · 9 comments

Comments

@bjorndown
Copy link

Currently the only way to tell valdr that a certain field is a number is by annotating it with @Digits or some custom annotation. Obviously this introduces some redundancy.

What would you think about extending valdr-bean-validation in such a way that for every field fields of some selected types it scans it also adds validation rules based on its type? scanned fields of a few selected types (tbd) it "generates"/automatically adds rules.

Say we have a field

class Foo {
    @Min(1)
    Integer bar;
}

Then its validation rule would look like this:

  "Foo": {
    "bar": {
      "digits": {
        "integer": 10,
        "fraction": 0
      },
      "size": {
        "min": 1
      }
    }
  }

Thanks for your thoughts on this.

@marcelstoer
Copy link
Collaborator

Thanks! If you rephrase or redefine the statement

...for every field it scans it also...

then I'm very fond of this idea, makes a lot of sense.

Why not for every field? Based on the list of built-in valdr validators this would currently only be applicable to Numbers and their respective primitive types - possibly even fewer than that.
Challenge: what are digits#integer and digits#fraction for a Java Double?

@bjorndown
Copy link
Author

I have amended the proposal according to your suggestion.

Implementing said scheme for Integer-types should be straightforward.

As for floating point types, I don't see any good way to do this since there is no way to express their domain in terms of a fixed integer and fraction part, as is demanded by @Digits. If only @Digits had a precision attribute.

BigDecimal and BigInteger are even worse since they are of arbitrary length. With BigInteger we would at least know that fraction=0, but since we also need to specify integer that does not help.

So I guess it boils down to implementing this scheme for integer-types only.

With regard to the original motivation, namely that valdr does not know something is a number unless it is annotated in an appropriate way, that would be a start, but it is not totally satisfying.

Maybe it is not the right approach for what I want, which basically is for valdr and valdr-messages to know about builtin angularjs validations like type="number" on inputs.

@bjorndown
Copy link
Author

@marcelstoer It is not part of JSR303, but one way to tell valdr that a field is a number would be to add a simple "number" rule for all sub classes of Number. Then we would somehow need to hook up valdr to angular's number validator.

What do you think about extending this plugin's scope like that?

@philippd
Copy link
Collaborator

I don't think that this helps a lot for the client side validation. If I understand your idea correctly, this would just check that the user enters a number (at least that's what Angulars number validator does if there is no min/max value set). So you would still have to go through all your forms and set the range manually to have a meaningful validation.

I would suggest to implement a project specific extension of JSR303 @Digits for the server side and add a constraint alias for the client side validator:

@Digits(integer = MyDecimal.INTEGER, fraction = MyDecimal.FRACTION)
@Retention(RetentionPolicy.RUNTIME)
@Target(FIELD)
@Documented
@Constraint(validatedBy = { })
@ReportAsSingleViolation
public @interface MyDecimal {

  int FRACTION = 6;
  int INTEGER = 12;
  int integer() default MyDecimal.INTEGER;
  int fraction() default MyDecimal.FRACTION;
  String message() default "{com.application.MyDecimal.message}";
  Class<?>[] groups() default { };
  Class<? extends Payload>[] payload() default { };

}

Client side:

.config(function (valdrProvider) {
    valdrProvider.addConstraintAlias('digits', 'com.application.MyDecimal');
  })

@marcelstoer
Copy link
Collaborator

One way or the other I think it's important that your markup contains <input type="number" (i.e. HTML5 number type) to give mobile browsers a chance to display the appropriate keyboard. BUT depending on the browsers you need to support this may have undesirable side effects.

It is not part of JSR303, but one way to tell valdr that a field is a number would be to add a simple "number" rule for all sub classes of Number. Then we would somehow need to hook up valdr to angular's number validator.

Depending on what you're actually trying to achieve this could be a pragmatic way to go. To be consistent with existing constraints we'd have to make number an officially supported valdr constraint. We already have valdr constraints that behave exactly like their AngularJS siblings (i.e. same implementation).

@bjorndown
Copy link
Author

Sorry, I'll try to focus. I have a field

class Foo {
    @Min(1)
    @NotNull
    private Integer bar;
}

which is part of a form

<form name="foo" novalidate valdr-type="Foo">
    <div valdr-form-group>
        <input class="form-control" type="number" name="bar"/>
    </div>
</form>

and I use valdrMessage for showing validation errors.

When I enter "a" into this field, valdr does not show a validation error, because it does not know about type="number". But the form is still invalid because angular's number validator kicked in. Which is ok, since it makes sense to check if it is a number before asserting whether it is within a certain range. What is not good is that I need to display this error somewhere else because valdrMessage only checks formField.valdrViolations.

In this particular case even the generating of the digits rule for integer-types would not help, since the number validator would come first. (I still like the idea, but I think it is not part of my problem)

I see two possibilities for solving the above problem:

  1. valdrMessage should learn about built-in angular validators
  2. Add a numbers validtion rule for sub classes of Number and hook it up to angular's validator.

Thanks for your feedback.

@bjorndown
Copy link
Author

We have decided to go with Philipp's approach since we think it is too rare a case that a numerical field's value is only limited by its type. As such, information expressed through annotations is usually not redundant, contrary to what I argued in the original post.

What we would like to discuss further is support for angular builtin validations in valdrMessage, for which I will open an issue presently.

From our point of view there is nothing more to do here. If you do not want to pursue any of the ideas, feel free to close this issue.

@philippd
Copy link
Collaborator

@bjorm I agree that being able to show AngularJS validation errors in valdr message would be a nice improvement. Thanks for opening a feature request for it!

@philippd
Copy link
Collaborator

see netceteragroup/valdr#58

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants