Bean Validation 2.0 Progress Report
It has been a few months since we’ve kicked off the work on Bean Validation 2.0 (JSR 380). We have made some good progress, so I’d like to give you a quick update on what has been achieved so far and what the next steps will be. This is planned to be the first post of a regular blog series with JSR 380 status updates.
Expert group formation
It all started with the review ballot of the JCP executive committee on the new JSR. The ballot was approved with a huge majority, allowing the JSR to proceed and create its expert group.
In a short time, individuals and representatives from multiple companies joined the EG, providing input and experiences from different angles and perspectives. This also gives us very good connections to the EGs of other specs such as JAX-RS or java.time (JSR 310) which will be beneficial for creating new (or improving existing) integrations with those.
First changes
With the first EG members on board, we didn’t lose time and began with the work on the new spec revision. One of the initial actions was to convert the spec document from DocBook into the fabulous AsciiDoc format. Using AsciiDoc comes with many advantages which make working on the spec a much more enjoyable experience:
-
It can be written using any text editor
-
Changes are easier to track, e.g. when reviewing pull requests on GitHub
-
We can include actual source files from the API instead of copying them
While that’s primarily a technicality interesting to those working on the spec, it also is beneficial for Bean Validation users, as you for instance can easily track all the changes done so far by examining a simple diff on GitHub.
Support for new date and time API
The primary theme in Bean Validation is the embrace of Java 8. Java 8 comes with a variety of improvements to the language (e.g. Lambda expressions and default methods) but also many useful additions to the class library.
One prominent example of the latter is the new date and time API (JSR 310).
Types such as Instant
, LocalDate
or ZonedDateTime
are now supported by the @Past
and @Future
constraints (BVAL-496):
@Future
private LocalDate deliveryDate;
@Past
and @Future
now also have a new attribute orPresent()
:
@Past(orPresent=true)
private final Year inceptionYear = Year.of( 2017 );
That’s useful for types such as Year
or LocalDate
which don’t represent a specific instant but rather an interval of time
and you want to consider the entire current year, day etc. as valid.
Another improvement related to the validation of dates and times is the new ClockProvider
extension point.
It allows you to specify what is "now" when validating @Past
and @Future
.
That comes in handy for instance if you want to work with the time and time zone of the currently logged in user in a multi-user, multi-timezone application.
But it’s also useful for (re-)running batch jobs with a different logical date than the current one or for testing with a fixed point in time considered as "now":
Validator validator = Validation.byDefaultProvider()
.configure()
.clockProvider( () -> Clock.fixed(
Instant.parse("2017-01-19T11:00:00.00Z" ), ZoneId.systemDefault() )
)
.buildValidatorFactory()
.getValidator();
Validation of Collection
, Optional
and other containers
Looking at language changes in Java 8, the newly allowed locations for annotations (type annotations) prove themselves a very useful feature for Bean Validation. By putting constraints to type arguments of parameterized types, it finally gets possible to apply constraints to the elements of collections in a concise and intuitive way (BVAL-508):
List<@NotNull @Email String> emails;
Putting the constraints to the String
type argument makes it apparent that they should not be applied to the list object itself, but rather to each contained element.
Similarly, it’s possible to apply constraints to the elements of an array:
String @NotNull @Email[] emails;
Also cascaded validation gets more flexible with that.
It’s now possible to mandate that the keys and values of maps should be validated
(so far, only values were validated) by using @Valid
like this:
Map<@Valid Customer, @Valid Address> primaryAddressByCustomer;
But it doesn’t end there.
The spec also defines support for java.util.Optional
:
Optional<@Past LocalDate> getRegistrationDate();
As well as for the hierarchy of property types in JavaFX:
Property<@Min(1) Integer> revenue;
Acknowledging that JavaFX provides dedicated non-generic sub-types of Property
for specific data types (e.g. StringProperty
or IntegerProperty
),
it is also supported to put constraints on the element itself in this case:
@Min(1)
IntegerProperty revenue;
This becomes possible by defining means of "automatic value unwrapping" for specific types such as the JavaFX ones. Check out the latest spec draft to learn more about how this is handled.
While the spec mandates support for type argument constraints on types such as Iterable
, Map
, Optional
and some more,
this can be easily extended via the ValueExtractor
contract.
This interface is used when the Bean Validation engine needs to obtain the elements of a constrained container.
Custom extractor implementations can be plugged in when bootstrapping a validator,
allowing to use type argument constraints with custom collection types such as the ones defined by Google’s Guava library (e.g. Multimap
or Table
):
ListMultimap<@Valid Customer, @Email String> emailsByCustomer;
We are considering to detect custom extractors using the service loader mechanism, allowing providers of container types to bundle corresponding extractors with their library and making them automatically available to you.
Validation of container elements is by far the most complex feature and we’d like to gather some more feedback on it before committing to it. Hence its current proposal is added as an appendix to the spec draft. We are eager to learn about your thoughts and feedback in general, but it’s especially important for this issue due to its complexity.
We’ve compiled a list of open questions around this proposal.
If you have thoughts on any of those, please make sure to let us know, e.g. by commenting below.
The snapshot builds of the reference implementation (Maven GAV org.hibernate:hibernate-validator:6.0.0-SNAPSHOT
) already implement the current proposal, so you can get it from the JBoss Maven repo in order to play with that feature.
Other improvements
While support for JSR 310 and validation of container elements have been the largest features we’ve been working on so far, there are some more smaller, yet very useful improvements.
E.g. all the built-in constraints are repeatable annotations now, allowing to define them several times without requiring the explicit @List
annotation ([BVAL-497]):
@ZipCode(countryCode = "fr", groups = Default.class, message = "zip code is not valid")
@ZipCode(
countryCode = "fr",
groups = SuperUser.class,
message = "zip code invalid. Requires overriding before saving."
)
private String zipCode;
ConstraintValidator#initialize()
has an empty default implementation now (BVAL-555),
simplifying the implementation of constraint validators that don’t need to access any constraint attributes.
You can simply omit the initialize()
method:
public class AssertTrueValidator implements ConstraintValidator<AssertTrue, Boolean> {
@Override
public boolean isValid(Boolean bool, ConstraintValidatorContext constraintValidatorContext) {
return bool == null || bool;
}
}
Another nice improvement is the usage of actual parameter names when reporting constraint violations for constraints on method or constructor parameters (BVAL-498).
Provided you have enabled reflective parameter name access during compilation (using -parameters
javac option),
Path.Node#getName()
will return the actual parameter name instead of "arg0", "arg1" for parameter nodes.
Next steps
With all these things in place, we feel it is the right time to put out an Alpha1 release of Bean Validation 2.0 and will post it for Early Draft Review to the JCP within the next days. This should get the discussed changes into the hands of more people out there and will let us improve and hone the features added so far.
In parallel we’ll continue with some other features from the backlog. Issues high on our priority list are:
-
Adding some new constraints as per our recent survey, e.g.
@NotEmpty
,@NotBlank
-
Separating the notions of message resolver and message interpolator (BVAL-217)
-
Ability to validate an object and a list of changes (BVAL-214)
We also contemplate the idea of using Java 8 Lambda expressions and method references for defining constraints without an explicit ConstraintValidator
implementation class.
This is already supported in the reference implementation:
ConstraintMapping mapping = ...
mapping.constraintDefinition( Directory.class ) // @Directory is a constraint annotation
.validateType( File.class ).with( File::exists );
We haven’t decided yet whether to put this into the spec or not. So we recommend you give it a try in the reference implementation and let us know about your thoughts. The feedback when sharing the idea on Twitter was very encouraging.
We are also working with the expert group for JAX-RS 2.1 (JSR 370) to further improve integration of the two specs, e.g. in the field of I18N.
This list of issues is not cast in stone, so if there is anything close to your heart, please speak up and let us know about your ideas.
Outreach
To get more closely in touch with the Bean Validation users out there, we’ve also submitted talks on Bean Validation 2.0 to several conferences. I will be presenting on it at JavaLand 2017 and have plans for some JUGs. You also can expect a new edition of the Asylum Podcast discussing Bean Validation 2.0 and working on a JSR in general in the next weeks. And you can find an interview with me on Bean Validation 2.0 on heise Developer (in German).
Raise your feedback
Bean Validation is a true community effort, so we are eager to learn about your suggestions and proposals. Don’t be shy, get a discussion started by dropping a comment below, posting to the feedback forum or sending a message to the Bean Validation mailing list.
Survey - Where do you use constraints on parameterized type?
For Bean Validation 2, we are working on the support for Collection<@Email String>
, Optional<@Min(3) Integer>
etc.
This has been a very common request and with Java 8 type use support, we can how achieve this.
However, we need your feedback on how you would use such feature.
Some context
We have support not only for collections, Optional
, Java FX properties but also for what we call custom parameterized containers.
We are wondering a few things about custom parameterized containers, namely how common they are.
This will affect the trade-offs we want to make on the design of that feature.
What is a container?
A container is a type that wraps and exposes one or several values.
The values is what you want to apply your constraints on.
And the container is parameterized because at use site, you can declare what type it actually contains.
For a Set<@Email String>
, we want to make sure every string in the set is an email.
Another less obvious example is a tuple class.
public class Pair<V1,V2> {
V1 getV1() { ... }
V2 getV2(); { ... }
}
public class Address {
// street1 is mandatory, street2 is optional
// represented via a Pair object
Pair<@NotNull @Size(max=250) String, @Size(max=250) String> streetFields;
}
Other examples are:
-
a tree structure containing specific object types
-
Guava’s Multimap (or any multimap for that matter)
Questions
We are wondering which type of parameterized containers you have in your code base and how likely you are going to apply constrains on their contained value. The form is a list of short questions that will help us get a better picture.
Here is the link to the form in a separate page or use it directly embedded below.
Many thanks!
Feedback needed - Which constraints should be added?
The work on Bean Validation 2.0 is in full swing and there is an issue where we could benefit from your help.
Recently we have been discussing whether any new constraints should be added to the specification or not.
Traditionally, Bean Validation stayed on the conservative side of things in this regard.
It defined only some generically applicable and widely useful constraints in the specification itself, e.g. @NotNull
, @Size
or @Pattern
.
Now Marco Molteni did a very interesting analysis on the constraints which are actually used in real world projects by running an analysis of open source projects hosted on GitHub. Only a specific type of project is hosted there usually (mostly libraries, as opposed to actual end user facing applications), so the numbers should be taken with a grain of salt. But nevertheless they are very interesting.
Marco's analysis shows that besides the BV-defined constraints @NotEmpty
and @NotBlank
- both defined by the reference implementation Hibernate validator - are very frequently used and thus are potential candidates for inclusion into Bean Validation 2.0.
The former asserts that the annotated string, collection, map or array is neither null nor empty, the latter validates that the annotated string is neither null nor empty, stripping leading/trailing whitespace.
Another candidate may be @Email
; but validation of e-mail addresses is a surprisingly complex business, with different people having different ideas and expectations of how a valid (or invalid) e-mail address should look like (take a look at the examples on Wikipedia to get an idea).
Hence I feel this is not something we should aim for in the specification.
To add some further data points, we created the following survey on constraints to be added potentially. Getting back many answers to this poll will help us to form a better understanding of what you, the users out there, really need. If you would like to see support for other constraints not mentioned in the survey, you can add them via the free-text field in the last question. These may be custom constraints defined by a Bean Validation provider, a third-party library or in your own projects which you see yourself using very frequently.
Taking the survey will take you only a minute, so give it a go. Thanks a lot for your help!
Bean Validation 2.0 - A new JSR is born!
Today I've got some great news to share with you: a new revision of the Bean Validation spec is about to be kicked off!
Over the last weeks, we've been busy with preparing a proposal for this JSR and I've submitted it to the JCP (Java Community Process) last week. You can find the proposal for "JSR 380: Bean Validation 2.0" on jcp.org.
In the following, let's take a look at what we think should be part of Bean Validation 2.0 and what we've planned as the next steps.
Looking back...
Bean Validation 1.0 and 1.1 (JSRs 303/349) saw a huge adoption by the Java community and are integrated with a wide range of technologies, be it other Java standards (e.g. CDI, JPA, JAX-RS) or 3rd party libraries and frameworks such as Spring, Vaadin and many, many more.
The main contribution of Bean Validation 1.1 - the declarative validation of method-level constraints - has been integrated into techs such as CDI and Spring, making it a breeze to write expressive API contracts with constraints which are automatically validated upon execution.
Bean Validation 1.1 has been finalized three years ago and Java continued to evolve since then. Java 8 - released in 2014 - brings many very interesting language features to the table, but also adds a new time and date API and much more.
...and forward
So it's about time that Bean Validation supports new JDK types such as LocalTime
or Optional
, but also takes advantage of new (language) features such as type annotations, repeatable annotations, reflective parameter name retrieval, lambda expressions etc.
To give just one example, let's consider the requirement of applying constraints to the elements of a specific collection. This has been a long-standing feature request, but we could never find a way to solve it generically in an acceptable manner.
Java 8 finally provides the perfect tool to solve this issue: type annotations. Annotating type parameters of collections is a very intuitive way to apply constraints to collection elements (and not the entire collection itself):
List<@Email String> emails;
Java 8 provides the required APIs to retrieve the constraint annotation from the type parameter and apply the validation accordingly.
But it doesn't stop there. Repeatable annotation types will make it less verbose to specify several constraints of the same type one and the same element. Reflective parameter name retrieval will provide better validation messages out of the box when validating constraints on method parameters. Lambda expressions might be a useful vehicle to express small ad-hoc validation routines.
What else?
While we envision supporting and leveraging Java 8 as the "main theme" of Bean Validation 2.0, we hope to address some other issues, too. E.g. there may be support for more customized payloads of constraint violations. Also a builder API for constraint violation exceptions might be useful. As would an API for validating an object graph assuming a list of changes to be applied. Check out the JSR 380 proposal for some more ideas we have.
While the baseline for Bean Validation 2.0 will be Java 8, we'll also be tracking the ongoing work for Java 9 and work towards making Bean Validation ready for Java 9 and its module system as far as possible.
As the time-line of Bean Validation 2.0 is quite compact, we are very eager to hear from you, the community of users, and learn what would be the things most useful to you. For sure we won't be able to address all potential ideas out there. So if there are features close to your heart which you'd really love to see in the spec, be sure to speak up and let us know.
What's next?
As per the rules of the Java Community Process, the Bean Validation 2.0 JSR is currently up for review by the JCP executive committee. After that, there will be an approval ballot and we will hopefully be ready to go and kick off the work on actual spec changes, prototyping new features in the reference implementation and so on.
So if you ever wanted to contribute to a Java Specification Request - be it just by voting for issues, opening new feature requests or actually working on the specification, its reference implementation and the test compatability kit (TCK) - then this is the perfect time. If you are a member of the JCP, you also can join the expert group, we'd be very happy to have you aboard.
Whether EG member or not, in order to get the discussion on this JSR proposal started, just drop a comment below, post to the feedback forum, shoot a message to the Bean Validation mailing list or comment on specific issues in the tracker.
We are looking forward to hearing from you and get Bean Validation 2.0 rolling!
Bean Validation TCK 1.1.4.Final released
Exactly one year after the last maintenance release we've published version 1.1.4.Final of the Bean Validation TCK today. It contains exactly one issue, BVTCK-68, which is about the removal of two tests from the TCK which could not be tested in a portable manner across containers. Check out the issue itself for the complete story.
As always, the new TCK version is available for download as TAR.GZ and ZIP on SourceForge. Alternatively you can obtain the test suite via Maven, Gradle etc. using the coordinates org.hibernate.beanvalidation.tck:beanvalidation-tck-tests:1.1.4.Final.
More information about the Bean Validation TCK can be found here and the TCK reference guide. In case you have any questions or ideas around the Bean Validation specification in general or the TCK in particular, don't hesitate to contact us through our mailing list.
Latest news
Stay up to date, subscribe to the news feed.