[jsr372-experts] Re: [jsr372-experts mirror] Re: 1078-DataModelRegistrable

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Sun, 7 Jun 2015 23:45:56 +0200

Hi there,

I just attached the changebundle for this at:

The main and only addition to the public API is the annotation
@FacesDataModel that when applied to a user provided DataModel registers it
with the runtime. Via an attribute it declares the class it's able to wrap.

As for the Implementation, those classes are collected in CdiExtension#

After the collecting phase the collected classes are sorted in CdiExtension#
processBean such that if an instance of any class from the collection would
be a subtype of any other class in that collection, it has to appear before
it. Apart from this constraint the order does not matter.

This sorting allows a sequential scan through the collection to find the
best matching type. E.g. suppose the collection would contain List.class
and Collection.class, then List.class would appear before Collection.class.
Given an instance of ArrayList, List would match before Collection.

The resulting collection is then made available via CDI in application
scope, albeit via an implementation specific name. For Mojarra I
choose "comSunFacesDataModelClassesMap"
for this name.

Finally UIData obtains said collection via CDI and does a filter/findFirst
on it checking if the object for which a DataModel wrapper needs to be
found is assignable to the type that each DataModel declared to be able to
handle. As explained above, the first match is the best batch.

One design decision was to have the custom DataModel check to be done
*after* all existing checks for wrappers are done (e.g. the hardcoded
checks for List, Collection, Iterable, etc). This means that a custom
DataModel cannot override those types. This was done to ensure maximum
backwards compatibility, although one could argue it's more powerful to
check for the custom DataModels first.


Kind regards,
Arjan Tijms

On Wed, Jun 3, 2015 at 1:04 AM, arjan tijms <arjan.tijms_at_gmail.com> wrote:

> Hi y'all,
> Just some quick update on this. After a small hiatus I returned to this
> issue and started implementing it. There were a few small challenges that
> made this issue a bit more difficult than initially anticipated.
> Specifically the fact that registering a DataModel for say java.util.List
> requires some clever matching of class types, as the runtime object
> encountered can be e.g. an ArrayList or whatever sub type, and the
> "whatever sub type" can have a chain of super classes and a tree of
> interfaces and their super interfaces, where each super class can also have
> its own tree of interfaces and their super interfaces.
> A small hindrance is also that UIData (of course) contains implementation
> code, but it's in the API project of Mojarra which can't/doesn't have
> utility classes. So UIData and UIRepeat can't share between each other
> directly, nor can either of them use a utility class from the impl. project.
> Nevertheless I'm making good progress and hope to present a changebundle
> for evaluation soon.
> Kind regards,
> Arjan Tijms
> On Tue, Mar 10, 2015 at 9:17 AM, Hanspeter <hampidu_at_gmail.com> wrote:
>> +1
>> Hanspeter
>> Am 09.03.2015 20:41 schrieb "Frank Caputo" <frank_at_frankcaputo.de>:
>>> +1
>>> Ciao Frank
>>> Am 09.03.2015 um 17:31 schrieb Bauke Scholtz <balusc_at_gmail.com>:
>>> +1
>>> Cheers, B
>>> On Sun, Mar 8, 2015 at 11:22 PM, arjan tijms <arjan.tijms_at_gmail.com>
>>> wrote:
>>>> Hi,
>>>> As the third part of extending the data model wrappers for UIData and
>>>> UIRepeat, it was suggested to make data model wrappers registrable by
>>>> the user. Issue JAVASERVERFACES_SPEC_PUBLIC-1078 was created for this,
>>>> but it was also mentioned as part of JAVASERVERFACES_SPEC_PUBLIC-1103.
>>>> I took a quick look, and now with CDI available it seems almost
>>>> trivial to implement this.
>>>> JSF would provide a CDI qualifier annotation like:
>>>> @Retention(RUNTIME)
>>>> @Target(TYPE)
>>>> @Inherited
>>>> @Qualifier
>>>> public @interface FacesDataModel {
>>>> Class<?> forClass();
>>>> }
>>>> The user then provides something like the following:
>>>> @FacesDataModel(forClass=MyObject.class)
>>>> public class MyDataModel<E> extends DataModel<E> {
>>>> // datamodel methods
>>>> }
>>>> The runtime then looks up an instance of that via CDI (just like
>>>> happens now for CD Converters and Validators, which is almost a
>>>> one-liner in Manfred's CDIUtils).
>>>> Thoughts?
>>>> Kind regards,
>>>> Arjan Tijms