[bv-dev] Conflict issue with value extraction and JavaFX collection types
Hendrik Ebbers
hendrik.ebbers at me.com
Thu May 11 11:35:38 EDT 2017
Today I created some JavaFX based UI by using hibernate-validator 6.0.0.Beta1
This version was released today and already integrates the support for the JavaFX ListProperty. I created a PR for all the samples (https://github.com/hibernate/hibernate-demos/pull/24).
While doing the samples I found a problem in JBV 2.0 in combination with Collections. From my point of view at least one general (maybe Provider based) method for validation is missing in the Validator class. I created an issue: https://hibernate.atlassian.net/browse/BVAL-622
Since the issue contains the description simply copy it:
I wrote some JavaSE sample to test the new ValueExtractor classes for JavaFX like ListPropertyValueExtractor. In that case I miss an important feature in the base API.
Let's say I have a model that has the following fields:
@NotEmpty(message = "Name sollte nicht leer sein!")
private final StringProperty name = new SimpleStringProperty();
private final Property<@Min(50) Integer> count = new SimpleObjectProperty<>();
@Size(min=1, max=4)
private final ListProperty<@Size(min=2, max=32) String> tags = new SimpleListProperty<>(FXCollections.observableArrayList());
Next I bind all the properties of the model to UI nodes. Example:
nameField.textProperty().bindBidirectional(model.nameProperty());
In addition I want to do a validation call whenever a value in the model changes. For the name property this can be done by the following code:
nameErrorNode.visibleProperty().bind(Bindings.createBooleanBinding(() ->
!validator.validateProperty(model, "name").isEmpty(),
model.nameProperty()));
By doing it like this only the name property will be validated whenever it changes. It would be wrong to validate the complete model in this case.
I can simply do the same for the list:
tagErrorNode.visibleProperty().bind(Bindings.createBooleanBinding(() ->
!validator.validateProperty(model, "tags").isEmpty(),
model.tagsProperty()));
In this case the list will be validated whenever the list changes. This happens for example if a new element will be added, updated or removed. Let's imagine a list with 1_000_000 entries or so. In that case I do not want to validate the complete list when I update an element. Based on this I think that an additional method next to
Validator.validateProperty()
is needed in the JBV Spec to validate internal elements.
> Am 21.04.2017 um 08:31 schrieb Gunnar Morling <gunnar at hibernate.org>:
>
> Right, it's an issue with parallel class hierarchies in general. The
> same could happen during constraint validator resolution. In both
> cases an extractor (or validator) for the specific sub-type must be
> provided to resolve the ambiguity. This would also address your case
> of cached and real value.
>
> Based on the preference of option 2), I've added this to the pending
> PR in the section on built-in extractors:
>
> ===
> Compatible implementations provide value extractors for the following
> types out of the box:
>
> [...]
>
> * javafx.beans.observable.ObservableValue; value() must be invoked
> with the observable value, passing null as node name; the extractor
> must be marked with @UnwrapByDefault
>
> * javafx.beans.property.ReadOnlyListProperty and
> javafx.beans.property.ListProperty; indexedValue() must be invoked for
> each contained element, passing the string literal <iterable element>
> as node name
>
> * javafx.beans.property.ReadOnlyMapProperty and
> javafx.beans.property.MapProperty; both map keys and map values are to
> be supported; keyedValue() must be invoked by the map key extractor
> for each contained key, passing the string literal <map key> as node
> name; keyedValue() must be invoked by the map value extractor for each
> contained value, passing the string literal <map value> as node name
> ===
>
> 2017-04-19 14:42 GMT+02:00 Hendrik Ebbers <hendrik.ebbers at me.com>:
>> I think this is not a JavaFX specific problem. This can happen everywhere if
>> you have defined extractors for 2 interface types and and have an
>> implementation of both.
>> In this specific example I would prefer to define ListProperty as a List.
>>
>> In general I think that this problem might / will happen in other frameworks
>> and APIs, too.
>>
>> I added such an example in a mail about the usage of annotations in the
>> generic information:
>>
>> Until now I only worked with lists and here the approach is quite nice.
>> Sadly it won’t work always. By adding an constraints annotation to the
>> generic type of the list we know that the annotation mentions the content of
>> the list. But this is only working because of one point: The generic type of
>> a collection defines the type of the collection content. This works fine for
>> collections (and for example JavaFX properties) but in other cases this will
>> end in problems.
>>
>> Let’s say we have the following 2 interfaces:
>>
>> public interface CachedValue<V> {
>> V getCachedValue();
>> }
>>
>> public interface RealValue<V> {
>> V getRealValue();
>> }
>>
>> Based on this interfaces we can easily create a new class that implements
>> both interfaces:
>>
>> public class CachableValue<V> implements CachedValue<V>, RealValue<V> {
>>
>> private V cachedValue;
>>
>> @Override
>> public V getCachedValue() {
>> return cachedValue;
>> }
>>
>> @Override
>> public V getRealValue() {
>> V realValue = receiveValueFromServer();
>> cachedValue = realValue;
>> return realValue;
>> }
>>
>> private V receiveValueFromServer() {
>> return ServerConnector.getCurrentValue(); //Some fake code
>> }
>> }
>>
>>
>>
>>
>> Am 18.04.2017 um 14:57 schrieb Emmanuel Bernard <emmanuel at hibernate.org>:
>>
>> I'm not using JavaFX but I would be in favor of 2. because it let's
>> people put a size constraint on the List.
>>
>> Have you considered a blog post to get more feedback. Here people don't
>> use JavaFX or are shy.
>>
>> On Wed 17-04-12 16:16, Guillaume Smet wrote:
>>
>> Hi,
>>
>> We are refining the value extraction work and one of the remaining tasks is
>> to throw a proper exception if we have ValueExtractors defined in parallel
>> hierarchies for a given type.
>>
>> This led to discovering the below issue with the JavaFX collection types.
>>
>> Let's take the ListProperty example (we have the same issue with Set and
>> Map): ListProperty inherits from ObservableValue and from List.
>>
>> For now, it uses (by chance) the ObservableValue extractor which unwraps
>> the value by default. So basically:
>> @NotNull
>> private ListProperty<String> listProperty = new
>> ReadOnlyListWrapper<String>( null );
>> will return a violation.
>>
>> With the new conflict detection, it will throw an exception as it's unable
>> to find ONE most specific ValueExtractor as there are 2 valid candidates:
>> ObservableValueValueExtractor and ListValueExtractor.
>>
>> If we want to solve the conflict, we need to introduce a specific
>> ValueExtractor for ListProperty and decide of its behavior.
>>
>> We have 2 possibilities:
>> 1/ consider ListProperty as an ObservableValue and thus simply unwrap the
>> list and validate the constraint against the list. In the above example,
>> @NotNull would then apply to the inner list. Same behavior as explained
>> above.
>> 2/ consider ListProperty as a List. Thus the value extractor would iterate
>> over the element of the list. In the above case, it won't return a
>> violation. In the below example, the @NotNull would refer to listProperty
>> itself and the constraints on the elements of the list would be validated:
>> @NotNull
>> private ListProperty<@Size(min = 3) String> listProperty = new
>> ReadOnlyListWrapper<String>( null );
>>
>> Gunnar and I are in favor of 2/ but it changes the current behavior as the
>> @NotNull would refer to the container instead of referring to the wrapped
>> value.
>>
>> We would really like to have some feedback from people using JavaFX.
>>
>> Thanks!
>>
>> --
>> Guillaume
>>
>>
>> _______________________________________________
>> beanvalidation-dev mailing list
>> beanvalidation-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
>>
>>
>> _______________________________________________
>> beanvalidation-dev mailing list
>> beanvalidation-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
>>
>>
>>
>> _______________________________________________
>> beanvalidation-dev mailing list
>> beanvalidation-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
>
> _______________________________________________
> beanvalidation-dev mailing list
> beanvalidation-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/beanvalidation-dev/attachments/20170511/1a913fc7/attachment-0001.html
More information about the beanvalidation-dev
mailing list