Should getters be validated when they are called?
The expert group is agonizing on a specific issue. We need your feedback. Should getters be considered regular methods and thus be validated when called?
The problem
Existing applications put Bean Validation constraints on properties (ie getters). If we enable validations when getters are called, some applications might fail and Bean Validation would not be backward compatible. Besides, it is unlikely that you want to validate genuine getters when they are called. These are state, not operations for the most part.
First off what does it mean to be a getter. A method is a getter if:
- its name starts with
is
, has no parameter and its return type isBoolean
- or its name starts with
get
and has not parameter
If in your service (say a CDI bean), you have an action method with
no parameter and starting with get
, and if you have added constraints
to validate the return value upon method call, we cannot differentiate
this action method from a genuine getter.
We have several solutions to work around the problem and we would like to know which one you prefer.
Solutions
We can use a few levers to work around the issue:
- ask you to enable method validation explicitly
- offer a coarse or fine grained solution to change the default behavior
Solution 1: enable method validation out of the box
If method validation is enabled out of the box then the sensible default is to exclude getters from method validation.
This approach is friendly out of the box and will work as expected most of
the time (except for action methods with no parameter, starting with get
and with constraints on the return value).
The downside of this approach is that in this very specific case where an action method is also a getter, method validation would be disabled out of the box and a manual intervention would be necessary.
You can change the default approach in two ways:
Solution 1.a: global flag
Use a global flag to disable method validation entirely or ask for getters
to be validated upon call. You would use validation.xml
for that:
<method-validation mode="INCLUDE_GETTERS"/>
There is no way to change the behavior for a specific (set of) class.
Solution 1.b: fine grained flag
An alternative solution is to change method validation behavior in a much more fine-grained approach:
- set the default approach globally
in
validation.xml
- set or override the setting for a given package (including sub-packages?)
via
@ValidateOnCall
as a package annotation (orvalidation.xml
) - set or override the setting for a given class
via
@ValidateOnCall
as a type annotation (orvalidation.xml
) - set or override the setting for a given method
via
@ValidateOnCall
as a method annotation (orvalidation.xml
)
A @ValidateOnCall
annotation can be overridden in validation.xml
like we do for
constraints declarations.
public class AwesomeService {
// not a getter - validated by default
@NotNull Currency provideMainCurrency(@ISO @NotNull String country) { ... }
// not a getter - validated by default
@NotNull Currency getAlternativeCurrencies(@ISO @NotNull String country) { ... }
// getter - must use @ValidateOnCall to activate
@ValidateOnCall(mode=INCLUDE_GETTERS)
@NotNull getAllCurrencies() { ... }
}
Note that, we could put @ValidateOnCall(mode=INCLUDE_GETTERS)
on the package
of service classes
@ValidateOnCall(mode=INCLUDE_GETTERS)
package com.acme.gladiator.action;
In this case, getAllCurrencies()
does not need to be annotated with @ValidateOnCall
.
Solution 2: disable method validation out of the box
In this situation, a user wanting to enable method validation needs to both:
- add the constraints on methods
- add the flag to enable method validation
The method validation flag would both allow it to be enabled and decide if getters should be considered.
This approach is the least surprise approach as nothing is happening that you have not explicitly asked for. The drawback is that it requires a manual intervention to enable method validation in a given archive which is not groovy.
Solution 2.a: global flag
For all archives using method validation, a META-INF/validation.xml
file must
be added. The file would contain the explicit setting:
<method-validation mode="INCLUDE_GETTER"/>
There is no way to change the behavior for a specific (set of) classes.
Solution 2.b: fine grained flag
As described in the previous section, we could enable method validation at
the package, class and method level using either a @ValidateOnCall
annotation
or via the validation.xml
. In this approach, validation.xml
is not mandatory
to enable method validation provided that you use @ValidateOnCall
in your code.
So what's your favorite?
My personal favorite is to enable non-getter method validation out of the box and offer fine-grained options to override the behavior. That's solution 1.b. My reasoning is the following:
- I want ease of use and method validation enabled by default
- actions methods named like a getter, with no parameter and constraints on its return value will be rare - return value constraint are less common than parameter methods
Some in the expert group do prefer solution 2.a or 2.b.
What's your take? And why do you prefer this approach?
Public review ballot favorable to Bean Validation 1.1
The Java expert comity has just approved the public review version of Bean Validation 1.1.
What does that mean for the spec? We keep going and carry on our work to finalize the specification.
Onwards.
Bean Validation 1.1 Beta 2 is out
With Hibernate Validation, the reference implementation catching up with the public review draft, we found a couple of minor glitches to actually implement the specification. We did a minor release to fix those glitches.
Check out the specification and make sure to use 1.1.0.Beta2 if you plan on implementing the specification early.
Public Review Draft for Bean Validation 1.1
Last Friday I have handed over the Public Review Draft to the JCP.
Beyond the new features and polishing of existing ones (see below), the Public Review Draft marks the point where:
- the community at large is invited to comment on the specification before the last leg of work towards the final release starts
- the JCP executive commitee votes on the current work at the end of the review period
We have been doing our work in the open but if you have not yet paid much attention now is the time to fix that :)
You can access the draft on this website. All changes are marked with a different color. Green for additions, yellow for changes and struck through red for removals . This will help you see what has changed precisely.
Please send us your remarks and comments:
- on our mailing list
- in our issue tracker
- or on the Bean Validation forum
If you want to go to the next step and contribute, send us an email to the mailing list and read how to contribute.
What's new in this draft
A lot of work has been done to polish or rework the features introduced in the first draft. We have also added a few additional improvements:
- improved integration with CDI: dependency injection, component lifecycle management and interception for method validation
- add rules describing method validation in particular how an interception technology ought to integrate: this will offer better portability
- add support for cross parameter validators on method validation
- add metadata APIs to identify constrained methods
- add support for group conversion (i.e., change the targeted group when cascading validation)
- clarify that composed constraints should fail fast when
@RepostAsSingleViolation
is present - support
CharSequence
(used to beString
) for built-in constraints
Contributions
As usual, many thanks to the community for its feedback, the expert group for its work. Special thanks to Gunnar and Hardy who worked round the clock this past two weeks to integrate all planned improvements in the specification document.
Fine control over method validation in Bean Validation... or not!
I need your feedback on whether or not you need fine controls on method validation.
Some context
Bean Validation 1.1 introduces the idea of method validation. When the method is called, parameters and return value can be validated. The constraints are of course defined as Bean Validation constraint annotations.
I am working on the chapter describing how interceptor technologies like CDI, EJB, Spring, Guice, AspectJ should integrate it.
We have decided to convert most of the recommendations into mandatory rules. In particular, methods annotated with constraints should be validated by the integration technology by default.
Early in the design we have introduced an annotation @MethodValidated
that lets you control a few things:
- which group should be used for validation (defaulting to
Default
) - what part should be validated: parameters, return value, both or none
This annotation made sense when validation was not on by default but I am now questioning its usefulness.
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. They also go from easy to more convoluted. Are you up for the challenge?
Note that I have added a bonus question in the end.
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?
public class UserService {
@MethodValidated(validationMode=NONE)
public void createUser(
@NotEmpty @Email String email,
@Valid Address address ) {
...
}
}
If you have a use case, would it be fulfilled with the @MethodValidated
annotation as described?
What's your use case for changing the default group?
@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?
@MethodValidated.validationMode
let's you validate both method
parameters as well as return value, or either one of them or none at all.
@MethodValidated(validationMode=PARAMETERS)
public class UserService {
@Valid
public User createUser(
@NotEmpty @Email String email,
@Valid Address address ) {
...
}
}
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:
@MethodValidated
definitions on a method overrides the ones on a class@MethodValidated
definition on a subclass overrides the ones on superclasses
Here is an example
//example of rule 1
@MethodValidated(validationMode=PARAMETERS)
public class UserService {
@MethodValidated(validationMode=BOTH)
@Valid
public User createUser(
@NotEmpty @Email String email,
@Valid Address address ) {
...
}
}
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 hosted @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 ;)
What do you make of that?
You are a convinced @MethodValidated fan? What about the name?
We have never found a good name for this annotation anyways. If you like and want this annotation, how should it be named?
Yep that's the bonus question, sorry.
Conclusion
I realize that it must look like I am having a @MethodValidated
mid-life crisis but better now than later :D
Latest news
Stay up to date, subscribe to the news feed.