[bv-dev] Placing constraints on the container vs the contained type use (was Re: Support for constraints on container values (e.g. Collection<@Email String>))
Gunnar Morling
gunnar at hibernate.org
Wed Nov 23 05:14:06 EST 2016
Personally, I wouldn't bother supporting raw collection types. Raw type
usage is discouraged and may even go away in future Java versions IIUC. And
you don't know what value type is in there from looking at the declaration,
so we'd loose the ability to check correct constraint placement at compile
time.
2016-11-23 10:51 GMT+01:00 Emmanuel Bernard <emmanuel at hibernate.org>:
>
> On 23 Nov 2016, at 09:06, Gunnar Morling <gunnar at hibernate.org> wrote:
>
>
>
> 2016-11-21 17:08 GMT+01:00 Emmanuel Bernard <emmanuel at hibernate.org>:
>
>>
>> On 7 Nov 2016, at 23:42, Hendrik Ebbers <hendrik.ebbers at me.com> wrote:
>>
>> Next to the „applyTo“ value all the constraint annotations needs
>> additional information to really validate all the given examples. In
>> addition a plugin must be present that defines how we can get the internal
>> value(s) of a class (in this case „StringProperty“).
>> Here are some code snippets that use additional information in the
>> annotations to define the validation:
>>
>>
>> @NotEmpty
>> @NotEmpty(applyTo = ConstraintsApplyTo.INTERNALS)
>> @NotEmpty(applyTo = ConstraintsApplyTo.INTERNALS, applyToInternalDepth =
>> 2)
>> @NotEmpty(applyTo = ConstraintsApplyTo.INTERNALS, applyToInternalDepth =
>> 3)
>> private List<List<List<StringProperty>>> spooky;
>>
>> @NotEmpty(applyTo = ConstraintsApplyTo.INTERNALS, valueContainerClass =
>> RealValue.class)
>> private RealValue<String> myValue;
>>
>> The „applyToInternalDepth“ value is used to define how often the
>> validator should get the internal value (depth). In the given example
>> „@NotEmpty(applyTo = ConstraintsApplyTo.INTERNALS, applyToInternalDepth
>> = 3)“ would validate the content of the „StringProperty“. In addition we
>> need some information for the container if the container implements several
>> interfaces. This could be defined in the annotation, too. In the example
>> this is defined by the „valueContainerClass“ value.
>>
>>
>> Hopefully we can converge on my idea not to have to
>> add valueContainerClass (see the other emails). But you do need a way to
>> identify the correct type parameter targeted. This is equivalent to the
>> @ExtractedValue which today has typeParameterHost and
>> either typeParameterIndex or typeParameterName to uniquely identify them.
>>
>> On the depth approach, your example would be more easily rewritten as
>>
>> @NotEmpty List<@NotEmpty List<@NotEmpty List<@NotEmpty
>> StringProperty>>> spooky;
>>
>> which clarifies everything. But let’s assume we have a type
>> ListOfListOfListOfStringProperty type. do we really want to support
>>
>> @NotEmpty
>> @NotEmpty(applyTo = ConstraintsApplyTo.INTERNALS)
>> @NotEmpty(applyTo = ConstraintsApplyTo.INTERNALS, applyToInternalDepth =
>> 2)
>> @NotEmpty(applyTo = ConstraintsApplyTo.INTERNALS, applyToInternalDepth =
>> 3)
>> private ListOfListOfListOfStringProperty spooky;
>>
>> or even
>>
>> @NotEmpty
>> // support nested levels by positioning ConstraintsApplyTo at the right
>> level
>> private List<@NotEmpty List<@NotEmpty @NotEmpty(applyTo =
>> ConstraintsApplyTo.CONTAINED_VALUES) ListOfStringProperty>> spooky;
>>
>> Or do we throw the towel and say that nested levels are not supported for
>> non parameterized type use locations? What I am realizing now is that this
>> option is available essentially to support containers that do not offer
>> parameterized type. And in a previous email, I am questioning that use case.
>>
>
> I'm also not convinced of this. In a way it seems to me like breaking
> encapsulation.
>
> When dealing with a type such as ListOfStringListsProperty, you don't know
> it's inner works from a variable declaration. Hence I'm doubting that you
> should be allowed to apply constraints to them from the outside. It's
> getting more apparent when thinking of more real-world domain-specific
> types:
>
> public class CustomerContacts {
> List<List<String>> contacts; // one single inner list contains the
> contacts valid at a given time
> }
>
> I don't think it makes sense to allow application of constraints "from the
> outside" when dealing with a property of CustomerContacts. It makes
> assumptions on the implementation of that type which is a dangerous thing
> to do. What if the implementation of CustomerContacts changes to be
> map-based? Existing constraint configurations given at the usage side would
> have to be adapted then.
>
> Instead the constraints should be declared within CustomerContacts itself.
>
> It's different for generic types. When dealing with a type like
> List<List<String>>, its "inner workings" are apparent to the user, i.e.
> it's reasonable to allow them to apply constraints to the elements of the
> inner list for instance.
>
>
> Ah interesting point of view. I’ve never thought of it that way.
>
> I think what I had in mind when I said containers with no parameterized
> type is the Java 4 style collections that only have raw type support.
>
> @Email(validApplyTo=ConsgraintsApplyTo.CONTAINED_VALUE)
> Collection emails;
>
> But back to the question, is that even a valid use case in 2016?
>
>
>
> _______________________________________________
> 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/20161123/3b87e146/attachment-0001.html
More information about the beanvalidation-dev
mailing list