[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