Metadata API to detect constrained methods and constructors
by Emmanuel Bernard
Hi all,
I am working on the section explaining how a interception technology
integrates with Bean Validation.
The proposal is also on the web site at http://beanvalidation.org/proposals/BVAL-274/
## Problem description
I was looking at how to compute whether or not method interception needs
to occur via on the metadata API.
The validation of method-level constraints comprises the following steps:
- Intercept the method call to be validated
- Validate the parameter values provided by the method caller using Validator#validateParameters() or Validator#validateConstructorParameters().
- If this validation yields a non-empty set of constraint violations, throw a ConstraintViolationException wrapping the violations. Otherwise proceed with the actual method invocation.
- Validate the result returned by the invoked method using Validator#validateReturnValue() or Validator#validateConstructorReturnValue().
- If this validation yields a non-empty set of constraint violations, throw a ConstraintViolationException wrapping the violations. Otherwise return the invocation result to the method caller.
I realised that we have a cumbersome API to detect whether or not
calling Bean Validation.
```
public boolean interceptMethod(Class<?> type, Method method) {
BeanDescriptor bean = validator.getConstraintsForClass( type );
MethodDescriptor methodDescriptor = bean.getConstraintsForMethod( method.getName(), method.getParameterTypes() );
return methodDescriptor != null;
}
public boolean validateMethodParametersWithFullNavigation(Class<?> type, Method method) {
BeanDescriptor bean = validator.getConstraintsForClass( type );
MethodDescriptor methodDescriptor = bean.getConstraintsForMethod( method.getName(), method.getParameterTypes() );
if ( methodDescriptor != null ) {
boolean validate = false;
for (ParameterDescriptor paramDescriptor : methodDescriptor.getParameterDescriptors()) {
validate = paramDescriptor.hasConstraints() || paramDescriptor.isCascaded();
if (validate) {
break;
}
}
return validate;
}
else {
return false;
}
}
public boolean validateReturnValueWithFullNavigation(Class<?> type, Method method) {
BeanDescriptor bean = validator.getConstraintsForClass( type );
MethodDescriptor methodDescriptor = bean.getConstraintsForMethod( method.getName(), method.getParameterTypes() );
if ( methodDescriptor != null ) {
boolean validate = false;
ReturnValueDescriptor returnValue = methodDescriptor.getReturnValueDescriptor();
if ( returnValue!=null ) {
return returnValue.isCascaded() || returnValue.hasConstraints();
}
else {
return false;
}
}
else {
return false;
}
}
```
`interceptMethod` is used to decide whether or not we intercept the method
at all. it can be used to disable the interceptor entirely.
`validateMethodParametersWithFullNavigation` is used to decide whether
or not we need to call `validator.validateParameters()`. If no violation
is found, we goa nd execute the method.
After the method returns, we call
`validateReturnValueWithFullNavigation` to decide whether or not to
validate return value.
There is of course the equivalent for constructor validation.
## Proposal
What I am proposing is to add two aggregate methods to
`MethodDescriptor` and `ConstructorDescriptor`.
```
/**
* Returns true if method parameters are constrained either:
* - because of a constraint on at least one of the parameters
* - because of a cascade on at least one of the parameters (via {@code @Valid})
* - because of at least a cross-parameter constraint
*/
boolean isConstrainedOnParameters();
/**
* Returns true if the method return value is constrained either:
* - because of a constraint on the return value
* - because validation is cascaded on the return value (via {@code @Valid})
*/
boolean isConstrainedOnReturnValue();
```
The implementation would then become
```
public boolean validateMethodParametersWithMethodDescriptorShortcuts(Class<?> type, Method method) {
BeanDescriptor bean = validator.getConstraintsForClass( type );
MethodDescriptor methodDescriptor = bean.getConstraintsForMethod( method.getName(), method.getParameterTypes() );
if ( methodDescriptor != null ) {
return methodDescriptor.isConstrainedOnParameters();
}
else {
return false;
}
}
public boolean validateMethodReturnValueWithMethodDescriptorShortcuts(Class<?> type, Method method) {
BeanDescriptor bean = validator.getConstraintsForClass( type );
MethodDescriptor methodDescriptor = bean.getConstraintsForMethod( method.getName(), method.getParameterTypes() );
if ( methodDescriptor != null ) {
return methodDescriptor.isConstrainedOnReturnValue();
}
else {
return false;
}
}
```
Of course the lookup of `BeanDescriptor` and `MethodDescriptor` only has
to be done once. The methods result is also likely being cached by the
interceptor being placed and these calls are probably only happening at
initialization time.
It seems to be it goes in the right
direction and expose things at a higher level for the metadata API
users.
Anyone against the proposed change?
An alternative solution is to use the fluent API to find constraints
public boolean validateMethodParametersWithFindConstraintAPI(Class<?> type, Method method) {
BeanDescriptor bean = validator.getConstraintsForClass( type );
MethodDescriptor methodDescriptor = bean.getConstraintsForMethod( method.getName(), method.getParameterTypes() );
if ( methodDescriptor != null ) {
return methodDescriptor.findConstraints().declaredOn( ElementType.PARAMETER ).hasConstraints();
}
else {
return false;
}
}
But it's not 100% in line with the `findConstraints()` API: it should only return constraints
that are on the element. Plus what is returned by the API is
`ConstraintDescriptor` which cannot differentiate where it comes from (parameter or method).
Emmanuel
12 years, 1 month
Why do we need @MethodValidated anyways?
by Emmanuel Bernard
I am still working on the chapter describing how interceptor tech
integrates bean validation. We have decided to convert most of the
recommendations into mandatory rules. In particular around having method
validation activated by default.
Having a annotation to control whether or not a method was validated
made sense when it was not enabled by default but I wonder if we still
need it.
I have a bunch of questions for you. I tried to keep them short and to
the point so feel free to answer them one by one.
## What's your use case for disabling method validation?
Why would you want to disable method validation on a given method or a
given class?
## What's your use case for changing the default group?
`(a)MethodValidated(groups=Heavy.class)` let's you change validation from
the `Default` group to the group of your choice - in this case `Heavy`.
Provided that we will offer support for group translation when cascading
<http://beanvalidation.org/proposals/BVAL-208/>
public class UserService {
public void createUser(
@NotEmpty @Email String email,
@Valid @ConvertGroup(from=Default.class, to=BasicPostal.class)
Address address ) {
...
}
}
do we really need the ability do decide which group to use to validate a
given method? What would be the use case?
To me it seems that it could makes sense to validate one group over
another based on:
- some environmental consideration
say a newbie user has more constraints on how it enters data
than an advanced user hence different groups
- the caller
say a branch of the code wants to apply different rules than
an other
In both case, it does not make sense to define the group via an
annotation on the method to be validated.
This would need to be a rather container specific behavior to let people
inject the right group for the right context.
## When would you want to only validate parameters or return values?
`(a)MethodValidated.validationMode` let's you validate both method
parameters as well as return value, or either one of them or none at all.
Do you have a use case in mind for such need?
## What inheritance rules make sense for `@MethodValidated`?
Assuming we have `@MethodValidated`, we need to define the overriding
rules.
We could decide that `@MethodValided` must be placed on the method to be
validated (no overriding rule), or we could try and add some or all of
the following rules:
1. `@MethodValidated` definitions on a method overrides the ones on a
class
2. `@MethodValidated` definition on a subclass overrides the ones on
superclasses
Interfaces make things harder as there would be no magic rule to decide
which definition has precedence over another in case of conflict.
We could consider that methods of a class implementing an interface
inherit the interface `@MethodValidated` definition (unless overridden).
And in case two interfaces define the same method, overriding the
`@MethodValidated` definition would be mandatory.
I can live with rule 1, I can support rule 2. but I feel that the rules
related to interfaces make things quite complex and not especially
readable. Plus I don't see why you would want to add `@MethodValidated`
on an interface. Not surprising as I don't see why one would do it on a
class method anyways ;)
## Conclusion
I realize that it must look like I am having a `@MethodValidated`
mid-life crisis but better now than later :D
12 years, 1 month
Cross parameter validation convergence
by Emmanuel Bernard
I would like to bring home cross parameter validation which is one of the main open issues in method validation.
We have been discussing it for literally 11 months, it's time to converge. If you could give your feedback quickly, Gunnar
might be able to add it to the spec in the next few days. I am already pushing him harder than I should to
move BV forward so give him some help :)
The following is a less readable copy of what you can find at http://beanvalidation.org/proposals/BVAL-232/
### Cross parameter validation and return value
Do we agree that validating both the parameters and the return value in a single
constraint validator is not a use case we want to cover?
To me that would be awkward to support it as we would need to execute the method
to validate it.
### Where to host cross-parameter constraints
We use the method as host to the return value constraints and possibly `@Valid`.
That is unfortunately also the natural place for cross parameter constraints.
I cannot think of another place to put them. There is also no easy way to add a
visual cue and differentiate a regular constraint from a cross param constraint
except by its meta annotation. We would rely on the user adding a visual cue in
the constraint name. Which kind of cue? Put `param` in the constraint name?
Any one can think of a better approach?
#### Bean Validation class
@interface CrossParameterConstraint {
public Class<? extends CrossParameterConstraintValidator<?, ?>>[] validatedBy();
}
interface CrossParameterConstraintValidator<A extends Annotation> {
void initialize(A constraintAnnotation);
[...]
}
> Question: does these different annotations/interfaces affect the metadata API?
>
> Question: can the same constraint annotation be annotated by both
> `@Constraint` and `@CrossParameterConstraint`: `@ScriptAssert` is a good candidate
> Note: how does composition plays into this?
#### Constraint coder class
@CrossParameterConstraint(validatedBy=CheckRetypedPasswordValidator.class)
@interface CheckRetypedPasswordParameter {
String message() default "...";
Class<?>[] groups() default {};
class<? extends Payload>[] payload();
}
class CheckRetypedPasswordValidator implements
CrossParameterConstraintValidator<CheckRetypedPasswordParameter> {
...
}
#### User code
class AccountService {
//cross param constraints
@CheckRetypedPasswordParameter
//return value constraints
@Valid @NotNull
User createUser(@NotEmpty String username, @Email String email, String password, String retypedPassword);
}
### What is the cross parameter constraint validator contract?
There has been two leading proposals. the others are described in the
[previous proposal][previous proposal].
#### Generic approach
interface CrossParameterConstraintValidator<A extends Annotations> {
void initialize(...) { ... }
boolean isValid(Object[] parameterValues, ConstraintValidatorContext context);
}
#### Type-safe approach (with annotation processors)
A more type-safe approach is to reuse the parameters signature of the method to match.
While the Java compiler cannot discover problems, both an annotation processor and the bean validation provider at runtime
can detect inconsistent contracts and raise respectively compilation errors and deployment time exception.
class CheckRetypedPasswordValidator implements
CrossParameterConstraintValidator<CheckRetypedPasswordParameter> {
void initialize(...) { ... }
boolean isValid(String username, String email, String password, String retypedPassword,
ConstraintValidatorContext context) {
...
}
}
#### Discussions
I think we must put the generic approach in because that's the only way to write non
method specific cross parameter constraints. Two examples of such constraints are
- script based constraints
- generic password retype checks based on the parameter indexes
`@AreEqual(indexes={2,3}, message="Passwords must be identical")`
So the remaining question is do we also support the type-safe approach in parallel?
I am inclined to think yes. We can do it on the same `CrossParameterConstraintValidator`
implementation:
class CheckRetypedPasswordValidator implements
CrossParameterConstraintValidator<CheckRetypedPasswordParameter> {
void initialize(...) { ... }
boolean isValid(Object[] parameterValues, ConstraintValidatorContext context);
boolean isValid(String username, String email, String password, String retypedPassword,
ConstraintValidatorContext context) {
...
}
}
If the method validated has a matching signature, we use it, otherwise we use the generic
method.
Do we keep the generic `isValid` method on the interface, thus forcing people to implement
it? Or is that an optional non constrained contract?
I am tempted to think that forcing is a better approach (the implementation can raise an
exception). Thoughts?
[jira]: https://hibernate.onjira.com/browse/BVAL-232
[previous proposal]: /proposals/BVAL-241/#cross_parameter
12 years, 3 months
Re: [bv-dev] Cross parameter validation convergence
by Gunnar Morling
Am 04.09.2012 00:55 schrieb "Emmanuel Bernard" <emmanuel(a)hibernate.org>:
>
> On Sat, Sep 01, 2012 at 06:38:58PM +0200, Gunnar Morling wrote:
> > Based on our discussions around the issue, I'm wondering whether we
> > should put cross-parameter validation into BV 1.1 at all.
> >
> > AFAIK none of the BV implementations provides such a feature, so with
> > this we'd be pretty much on the "innovating things" side of what a JSR
> > can do, opposed to the "standardization" side of the spectrum. IMO it
> > would be better to see cross-parameter validation be implemented by at
> > least one BV provider to gather some experiences and then standardize.
> >
>
> I personally would feel that we are missing a big and well defined set of
> use cases by leaving this unsolved. Look at how much complain we already
> have for cross field validations where we have *an actual solution*.
>
> Plus by not addressing it we might have APIs that won't support the
> notion down the road.
>
> > Note that a user can work around the lack of cross-parameter
> > validation by pulling the concerned parameters into a parameter
> > object, putting a class-level constraint on it and annotating the
> > parameter with @Valid.
>
> We can't realistically force people to change the natural signature of
> their method just to use Bean Validation. Do you really want to be the
> one in front of a 200 people crowd telling them that they need to change
> their method signature on the ground that you did not feel like
> supporting cross parameter validation? :)
Sounds like an interesting experience, being thrown at with rotten
vegetables by a furious crowd complaining about cross-parameter validation
not being supported ;)
>
> > If we really want to add this to BV 1.1, IMO we should only add the
> > generic approach and let implementors experiment with the type-safe
> > one.
>
> What is your reasoning for not wanting the type safe approach in?
It's just the number of open questions around this which I'm a bit
concerned about. For the other method validation things we could more or
less rely on the experiences from the existing implementations or added
smaller things like ParameterNameProvider.
Compared to that, there are several questions around (type-safe)
cross-parameter validation we'd be answering in the spec for the first
time. But it may be I'm just over-cautious here.
>
> > > We can do it on the same CrossParameterConstraintValidator
implementation [...] If the method validated has a matching signature, we
use it, otherwise we use the generic method.
> >
> > Wouldn't this contradict the idea of type-safety? If the validated
> > method signature gets changed without adapting the validator, silently
> > the generic method would be used, and also an annotation processor
> > couldn't raise an error since there is the generic method.
>
> That's a very good point and the solution needs to address that.
> The easiest solution I can see here is to have the following interfaces
>
> interface CrossParameterConstraintValidator<A extends Annotation> {
> void initialize(A constraintAnnotation);
> }
>
> interface GenericCrossParameterConstraintValidator<A extends
Annotation> {
> boolean isValid(Object[] parameterValues,
ConstraintValidatorContext context);
> }
>
> That brings back an idea Matt had that I forgot to reply to. Should we
> enforce at most one `isValid` method per
> `CrossParameterConstraintValidator`? With that problem in mind I am
> tempted to think that this is a good rule.
>
> People can still add several validators per cross parameter constraint.
Does it really make a difference whether two (typed) isValid() methods are
declared on one or two validators? I see this a bit similar to the
invocation of overloaded methods. As long as there is exactly one matching
signature, we can invoke it.
It may be challenging though to find the right isValid() method on several
validators in case of overloaded methods. In this respect it might even be
easier to allow for only one cross-parameter validator per constraint with
possibly several isValid() methods.
>
> That leaves one question: should we allow the mix of
> `GenericCrossParameterConstraintValidator` and non
> `GenericCrossParameterConstraintValidator` in a single constraint?
> That would indeed defeat the type-safety belt. On the other hands, it
> looks like a useful thing to be able to mix them when adding validators
> via the XML descriptor.
So far I don't see a good way around the problem of a transparent fallback
to the generic method. Safest (but most restrictive) would be to allow to
have either the generic method or exactly one matching type-safe one over
all validators for a constraint.
>
> > Thinking more about it, I'm wondering how we would represent
> > cross-parameter constraints in ConstraintViolations. What should be
> > returned by getInvalidValue()/getLeafBean()?
>
> I agree that this is not intuitive but we could return the `Object[]` of
> parameters when `getInvalidValue()` is called.
>
> The more general problem is that cross-parameter constraints (or
> should it be constraint validators) do not return the actual parameters
> being considered in violation.
Right. I guess we could either return the concerned indices from isValid()
(returning an empty list meaning no violation) or require isValid()
implementors to create the violation themselves.
>
> I imagine we could have a way to return parameter indexes as part of the
> `ConstraintViolation` or the `ParametersDescriptor` (see below).
>
> But do we want such a feature? And if yes, should it be statically
defined or dynamically
> defined. And if static, should it be hosted on the cross parameters
> constraint or the cross parameters constraint validator implementation?
>
> Note that if we manage to crack this nut, that's a step towards better
> support for cross field validations.
>
> > getPropertyPath() might
> > be an issue, too. For single parameters we have one node representing
> > the concerned parameter at the end of the violation's path, but this
> > wouldn't work here. Perhaps the path could just end with the method
> > node in that case.
>
> I think we just need to introduce a `ParametersDescriptor` that would
> represent this particular case. That seems the most natural approach.
Yepp. I think best is to try some things out in code and look how it works.
The use case could be an interceptor throwing an exception for violated
cross parameter constraints which prints out all required information in a
comprehensible manner.
>
> Emmanuel
--Gunnar
> _______________________________________________
> beanvalidation-dev mailing list
> beanvalidation-dev(a)lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
12 years, 3 months
Re: [bv-dev] Method Validation: Why Example 4.11 should be allowed
by Gunnar Morling
Right, XML mappings can indeed be helpful here.
I've written a post on beanvalidation.org [1] asking for feedback from a
broader audience. Maybe we gain some more insight through this.
--Gunnar
[1] http://beanvalidation.org/news/2012/08/29/methodvalidation-inheritance/
Am 29.08.2012 16:42 schrieb "Hardy Ferentschik" <hardy(a)hibernate.org>:
> Hi,
>
> I voted for the true PbC approach. As I mentioned before I was undecided
> and can see the
> Paul's and Matt's point.
>
> There are two reasons I voted for PbC now. First I think this the most
> typical use case where
> BV method validation will be used and, as Gunnar pointed out, the majority
> of existing PbC solutions
> took the no strengthening of preconditions road. The alternative is to
> allow weakening of preconditions
> (via ORing the constrains), but this is something we have not even
> discussed further and would not
> solve Paul's use case.
>
> Which leads me to the second reason I voted for PbC. Emmanuel reminded me
> of a very important
> BV feature, the XML configuration. Using it you can specify the
> constraints easily on the OrderService
> directly (to use our example again). So for me this covers even this use
> case without even using a
> option/flag.
>
> --Hardy
>
>
> On 27 Jan 2012, at 4:12 PM, Emmanuel Bernard wrote:
>
> > Just to get a better understanding of the dynamic here.
> > Can you all vote on what you think is the best approach for Bean
> Validation 1.1
> > http://www.doodle.com/qp78u6mqzetuas7p
> >
> > On 26 août 2012, at 09:42, Paul Benedict wrote:
> >
> >> I was reading the Hibernate Validator documentation today. Here was
> >> something that speaks to Gunnar's intentions:
> >>
> >> "When validating an object that implements an interface or extends
> >> another class, all constraint annotations on the implemented interface
> >> and parent class apply in the same manner as the constraints specified
> >> on the validated object itself."
> >>
> >> I buy into this 99% except when the parent class has no annotated
> >> constraints. Why not just make an exception for this case? I think
> >> that is so incredibly more reasonable than adding a custom
> >> implementation flag. Since constraints are meant to be compounded, a
> >> child should be able to add new constraints even if the parent never
> >> did.
> >>
> >> Paul
> >>
> >> On Wed, Aug 22, 2012 at 3:26 PM, Gunnar Morling <gunnar(a)hibernate.org>
> wrote:
> >>>> Gunnar, do you want to take the lead on 1. and 2.?
> >>>
> >>> Sure, I can do that. I'll prepare a blog post.
> >>>
> >>> Personally, I'm still reserved about adding such a feature. Maybe I
> >>> would change my mind if someone pointed out to an existing PbC
> >>> solution which provides such sort of feature/switch. What I've seen so
> >>> far is either prohibiting parameter constraints in sub-types (as we
> >>> currently do) or OR-ing all parameter constraint contracts in the
> >>> hierarchy (effectively applying the weakest one).
> >>>
> >>> An implementation-specific configuration switch might be a good
> >>> compromise. The spec still may define the current behavior as default
> >>> and mention that implementations may add means of configuring this.
> >>>
> >>> --Gunnar
> >>>
> >>>
> >>> 2012/8/22 Emmanuel Bernard <emmanuel(a)hibernate.org>:
> >>>> Reopening the debate here.
> >>>>
> >>>> Matt, java.util.Deque.push actually does describe the risk of NPE
> depending on the implementation.
> >>>>
> >>>> Let's take the OrderService that has been designed pre-BV 1.1 and
> that expressed constraints per JavaDoc. There are two options today to make
> it work:
> >>>>
> >>>> - update it to add Bean Validation 1.1 annotations in compliance with
> the JavaDoc
> >>>> - use BV's XML capability to add constraints on the interface without
> having to touch it
> >>>>
> >>>> Note that adding constraints not described on the interface javadoc
> would be a change of contract.
> >>>>
> >>>> But I do hear Paul's concern as well. With all the interfaces around,
> do we want to force people to host their constraints on them instead of on
> the implementation?
> >>>> How much of this is a usability constraint? On the other hand, today
> we enforce good practice. If we open up the Pandora box, there is no way to
> close it.
> >>>>
> >>>> I'd go and do a few things:
> >>>>
> >>>> 1. open up a JIRA with a summary of the problem
> >>>> 2. blog about it on beanvalidation.org and push people for feedback
> >>>> 3. get people to try a preview and give us feedback
> >>>>
> >>>> Gunnar, do you want to take the lead on 1. and 2.?
> >>>>
> >>>> If we are still on the fence, I'm tempted to let implementations
> provide an implementation specific configuration switch.
> >>>>
> >>>> Sebastian, OVal has had such features for a while AFAIK, what is your
> take on the subject?
> >>>>
> >>>> Emmanuel
> >>>>
> >>>> On 23 juil. 2012, at 20:38, Paul Benedict wrote:
> >>>>
> >>>>> I concur with Matt's point below. Because there hasn't been a
> >>>>> validation standard for most of Java's lifetime, most method
> >>>>> constraints are in javadoc contracts only. I think it's important for
> >>>>> the BV spec to recognize this fact -- not every precondition is
> >>>>> available for introspection at runtime. Thus, there is a long
> pedigree
> >>>>> here of people who could benefit from BV, if only by chucking their
> >>>>> custom validation code for BV.
> >>>>>
> >>>>> The OrderService is a great example due to the total absence of BV
> >>>>> annotations. I don't think the spec should assume the lack of BV
> >>>>> annotations is an intentional use of BV (i.e., no constraints). I can
> >>>>> only see two ways out of this problem to address this fact. Either
> >>>>> annotate OrderService to signify its validation is undefined or
> >>>>> annotate OrderService to signify validation is intended. Thoughts?
> >>>>>
> >>>>> Paul
> >>>>>
> >>>>> On Mon, Jul 23, 2012 at 9:16 AM, Matt Benson <mbenson(a)apache.org>
> wrote:
> >>>>>> Okay, point taken. Thanks for clarifying the distinction between
> >>>>>> pre/post-conditions corresponding to method parameters vs. return
> >>>>>> values here. Still, consider the JDK itself: the java.util.Deque
> >>>>>> interface imposes no requirements on the parameter to its #push()
> >>>>>> method, yet the java.util.ArrayDeque implementation forbids null
> >>>>>> elements and is declared as throwing an NPE if the parameter to
> >>>>>> #push() is null. I can fully understand your assertion that this
> >>>>>> violates DbC and even basic OO principles, but is it *necessary*
> that
> >>>>>> BV deny users the option to work with such a design? I'm not yet
> >>>>>> convinced of the harm it would cause, beyond implementation
> complexity
> >>>>>> (which IMO doesn't seem extensive), to permit a user to add
> decoupled
> >>>>>> validation constraints per Paul's example, or to customize a given
> >>>>>> implementation as in mine. Nothing here would prevent the purist
> user
> >>>>>> from operating per your recommendations.
> >>>>> _______________________________________________
> >>>>> beanvalidation-dev mailing list
> >>>>> beanvalidation-dev(a)lists.jboss.org
> >>>>> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
> >>>>
> >>>>
> >>>> _______________________________________________
> >>>> beanvalidation-dev mailing list
> >>>> beanvalidation-dev(a)lists.jboss.org
> >>>> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
> >>> _______________________________________________
> >>> beanvalidation-dev mailing list
> >>> beanvalidation-dev(a)lists.jboss.org
> >>> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
> >> _______________________________________________
> >> beanvalidation-dev mailing list
> >> beanvalidation-dev(a)lists.jboss.org
> >> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
> >
> >
> > _______________________________________________
> > beanvalidation-dev mailing list
> > beanvalidation-dev(a)lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
>
>
> _______________________________________________
> beanvalidation-dev mailing list
> beanvalidation-dev(a)lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
>
12 years, 3 months
Re: [bv-dev] Hosting of method validation methods
by Gunnar Morling
Hi,
I had created a local branch with a separate MethodValidator interface. I
can clean this up and push to Github.
For the “getter“ approach, getMethodValidator() would be defined on
ValidatorFactory, right? At least that was the original idea.
--Gunnar
Am 27.08.2012 10:19 schrieb "Emmanuel Bernard" <emmanuel(a)hibernate.org>:
> Did you end up playing with forMethod vs getMethodValidator ? I must
> admit, I'd like to see them in action before choosing.
>
> What do others think. this is a decision between the following two
> approaches:
>
> ## Fluent approach
>
> public interface Validator {
> MethodValidator<T> forMethod(Method method, T object);
> MethodValidator<T> forConstructor(Constructor<T> constructor);
> }
>
> public interface MethodValidator<T> {
> <T> Set<MethodConstraintViolation<T>> validateParameter(
> Object parameterValue, int parameterIndex, Class<?>... groups);
>
> <T> Set<MethodConstraintViolation<T>> validateAllParameters(
> Object[] parameterValues, Class<?>... groups);
>
> <T> Set<MethodConstraintViolation<T>> validateReturnValue(
> Object returnValue, Class<?>... groups);
> }
>
> ## Getter approach
>
> public interface Validator {
> MethodValidator getMethodValidator();
> }
>
> public interface MethodValidator<T> {
> <T> Set<MethodConstraintViolation<T>> validateMethodParameter(
> Method method, T object, Object parameterValue, int
> parameterIndex, Class<?>... groups);
>
> <T> Set<MethodConstraintViolation<T>> validateAllMethodParameters(
> Method method, T object, Object[] parameterValues, Class<?>...
> groups);
>
> <T> Set<MethodConstraintViolation<T>> validateMethodReturnValue(
> Method method, T object, Object returnValue, Class<?>... groups);
>
> <T> Set<MethodConstraintViolation<T>> validateConstructorParameter(
> Constructor<T> constructor, Object parameterValue, int
> parameterIndex, Class<?>... groups);
>
> <T> Set<MethodConstraintViolation<T>> validateAllConstructorParameters(
> Constructor<T> constructor, Object[] parameterValues, Class<?>...
> groups);
>
> <T> Set<MethodConstraintViolation<T>> validateConstructorReturnValue(
> Constructor<T> constructor, Object returnValue, Class<?>...
> groups);
> }
>
> ## Comparison
>
> The advantage of segregation is to avoid pollution of the
> main Validator interface especially if we add more methods in the future.
>
> The getter approach has the benefit of being simple.
>
> The fluent approach let's us factor the various methods between the
> methods and constructor calls and makes names less awkward. It also
> is consistent with some of the Bean Validation design using fluent APIs.
> The drawback of of fluent API is that it requires two method calls for a
> validation:
> • one to select the object and method
> • one to validate the parameters / return value
> It also creates a temporary object (returned by the first method).
>
> I have captured this discussion at
> http://beanvalidation.org/proposals/BVAL-241/#validating
> "DISCUSSION: Would a separate interface MethodValidator make sense?"
>
> Emmanuel
>
> On 1 août 2012, at 08:20, Gunnar Morling wrote:
>
> Hi,
>
> What do you other guys think?
>
> I'll go and create a branch to play around a bit with a separate
> MethodValidator interface. Maybe it helps to have something more specific
> which we then can compare and discuss.
>
> --Gunnar
> Am 26.07.2012 10:38 schrieb "Hardy Ferentschik" <hardy(a)hibernate.org>:
>
>>
>> On Jul 25, 2012, at 12:00 AM, Gunnar Morling wrote:
>>
>> > Hi,
>> >
>> > 2012/7/23 Hardy Ferentschik <hardy(a)hibernate.org>:
>> >> Hi all,
>> >>
>> >> Let me pick up yet another TODO from the current spec.
>> >>
>> >> Section "5.1.2. Method-level validation methods" [1] still contains a
>> TODO whether the methods for method validation should be hosted
>> >> on a different interface (other than javax.validation.Validator).
>> >>
>> >> At the moment all validation methods are hosted on
>> javax.validation.Validator. Personally I don't see a strong reason for
>> introducing
>> >> another indirection/interface. Does anyone have objections removing
>> the todo?
>> >
>> > I guess Emmanuel does :)
>> >
>> > Personally, I also used to be of the opinion that a separate interface
>> > doesn't really add much value. What made me pondering though was the
>> > recent discussion about adding new bean validation methods such as
>> > validateProperty(T object, Path property, Class<?>... groups);
>> >
>> > Following the interface segregation principle [1], it may indeed be a
>> > good idea to have two separate interfaces, one for standard bean
>> > validation and one for method validation. I think the main question
>> > is, who the consumers of the individual methods are. I think there may
>> > be a broader range of users of the bean validation methods
>> > (validate(), validateProperty() etc.) than of the method validation
>> > methods (validateParameters() etc.), which typically will only be
>> > invoked by authors of integration/glue code. So for users of the first
>> > group it would reduce complexity if the method validation stuff went
>> > into a separate interface.
>> >
>> > With respect to retrieving method validators, instead of something
>> > like Validator#forMethod(Method method) etc. I could also imagine
>> > ValidatorFactory#getMethodValidator(). Then one doesn't have to
>> > retrieve a new validator for each validated method/constructor.
>>
>> +1 for ValidatorFactory#getMethodValidator() in case we decide separate
>> interfaces
>>
>>
>> --Hardy
>>
>>
>> _______________________________________________
>> beanvalidation-dev mailing list
>> beanvalidation-dev(a)lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
>>
> _______________________________________________
> beanvalidation-dev mailing list
> beanvalidation-dev(a)lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
>
>
>
> _______________________________________________
> beanvalidation-dev mailing list
> beanvalidation-dev(a)lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
>
>
12 years, 3 months