jsr372-experts@javaserverfaces-spec-public.java.net

[jsr372-experts] Re: [jsr372-experts mirror] Re: [URGENT] @FacesDataModel inconsistencies with the spec (Re: Get your remaining items in)

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Tue, 14 Feb 2017 23:25:32 +0100

p.s. the utility/trick method I mentioned earlier is this one:


    @SuppressWarnings("unchecked")
    public <T> DataModel<T> createDataModel(Class<T> forClass, Object
value) {
        class LocalUIData extends UIData {
            @Override
            public DataModel<?> getDataModel() {
                return super.getDataModel();
            }
        }
        LocalUIData localUIData = new LocalUIData();
        localUIData.setValue(value);

        return (DataModel<T>) localUIData.getDataModel();
    }


That one implements the required lookup without having to know the details
of the Bean discovery and type resolution algorithms.

E.g.

Given:

public class Child1 {

}

and

package test.jsf23;

@FacesDataModel(forClass = Child1.class)
public class Child1Model<E> extends DataModel<E> {

@Override
public int getRowCount() {
return 0;
}

@Override
public E getRowData() {
return null;
}

@Override
public int getRowIndex() {
return 0;
}

@Override
public Object getWrappedData() {
return null;
}

@Override
public boolean isRowAvailable() {
return false;
}

@Override
public void setRowIndex(int arg0) {
}

@Override
public void setWrappedData(Object arg0) {
}

}


Then the following must work:

 DataModel<Child1> myModel = createDataModel(Child1.class, new Child1());
 System.out.println(myModel.getClass());

The result printed will be:

"class test.jsf23.Child1Model"

Hope this clarifies things.

Kind regards,
Arjan Tijms













On Tue, Feb 14, 2017 at 8:59 PM, Leonardo Uribe <leonardo.uribe_at_irian.at>
wrote:

> Hi
>
> AT> But I'm afraid it's, unfortunately, simply too late now.
>
> @Ed, Manfred: WDYT? a public review where you send feedback before 30 days
> and is it too late? why bother to send a public review if changes will not
> be accepted?
>
> regards,
>
> Leonardo Uribe
>
>
> 2017-02-14 14:14 GMT-05:00 arjan tijms <arjan.tijms_at_gmail.com>:
>
>> Hi,
>>
>> On Tuesday, February 14, 2017, Leonardo Uribe <leonardo.uribe_at_irian.at>
>> wrote:
>>
>>> Hi
>>>
>>> The problem here is there are other components that does not extend from
>>> UIData and uses DataModel.
>>>
>>
>> I'm absolutely aware of the necessity and the use case ;)
>>
>> But in my example the component that needs the DataModel instance doesn't
>> have to extend from UIData. Using the trick I mentioned you can instantiate
>> a separate UIData instance, then do the setValue/getDataModel trick on it.
>>
>>
>>> The closest example is UIRepeat, but there are others too.
>>>
>>
>> UIRepeat should already support it as well, but the issue is of course
>> components from third party libraries that don't extend from either UIData
>> or UIRepeat.
>>
>> Those can use the trick I mentioned though. Not ideal I know, but should
>> work for now.
>>
>>
>>
>>> The important thing is provide something somewhere that can be commonly
>>> accessed. For example, we could use a map or some generic interface stored
>>> in externalContext.getApplicationMap(). It that way, we can avoid add
>>> methods, but we provide what we need just agreeing with the name and what
>>> does it return. It is not perfect but it is something at least. Is this
>>> possible alternative feasible?
>>>
>>
>> I personally can't authorise anything, as I'm just a regular EG member
>> like you are. Only Ed can possibly allow this at this point.
>>
>> But I'm afraid it's, unfortunately, simply too late now.
>>
>> Kind regards,
>> Arjan Tijms
>>
>>
>>> regards,
>>>
>>> Leonardo Uribe
>>>
>>> 2017-02-14 11:41 GMT-05:00 arjan tijms <arjan.tijms_at_gmail.com>:
>>>
>>>> Hi Leo,
>>>>
>>>> On Tue, Feb 14, 2017 at 12:40 AM, Leonardo Uribe <
>>>> leonardo.uribe_at_irian.at> wrote:
>>>>
>>>>> Hi
>>>>>
>>>>> And the two methods proposed in Application class?
>>>>>
>>>>> public void addDataModel(Class<?> forClass, String dataModelClass)
>>>>> public DataModel createDataModel(java.lang.Class<?> forClass, Object
>>>>> value)
>>>>>
>>>>
>>>> The functionality for addDataModel at least is handled by CDI. That
>>>> can't be done by such a method, since it has to be done in the CDI
>>>> extension and the JSF Application class is not necessarily available by
>>>> then. The other way around, when the Application class is available it's
>>>> too late for CDI to accept new Bean<T> registrations, let alone annotated
>>>> types.
>>>>
>>>> The createDataModel method is practically there already, it's in
>>>> Mojarra:
>>>>
>>>> private DataModel<?> createDataModel(final Class<?> forClass)
>>>>
>>>> I would love to have added this method somewhere publicly, but I'm
>>>> afraid it's now too late for that :(
>>>>
>>>> What you CAN do however, is subclass UIData, then instantiate that.
>>>> Then do
>>>>
>>>> myUIData.setValue(someClassInstance);
>>>> UIDataModel<?> myModel = myUIData.getDataModel();
>>>>
>>>> That should guaranteed give you the right DataModel instance. If it's
>>>> covered by an existing known type it will return the wrapper for that,
>>>> otherwise the CDI version will be called.
>>>>
>>>> I humbly apologise for my oversight of adding that method at a public
>>>> place before. This is indeed my mistake. I will update the JavaDoc as you
>>>> requested to clarify this usage. For the next spec cycle we could add a
>>>> more convenient mechanism at the earliest opportunity.
>>>>
>>>> Once again my apologies and thanks for finding this.
>>>>
>>>> Kind regards,
>>>> Arjan Tijms
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>> I think that's the easiest way to fix it, because it standarize the
>>>>> way to access
>>>>> registered DataModel classes and encapsulate the algorithm that finds
>>>>> the right
>>>>> DataModel from a specified class.
>>>>>
>>>>> regards,
>>>>>
>>>>> Leonardo Uribe
>>>>>
>>>>> 2017-02-13 18:31 GMT-05:00 arjan tijms <arjan.tijms_at_gmail.com>:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> On Mon, Feb 13, 2017 at 11:35 PM, Leonardo Uribe <
>>>>>> leonardo.uribe_at_irian.at> wrote:
>>>>>>
>>>>>>> I have been checking the related documentation of @FacesDataModel
>>>>>>> and the
>>>>>>> unofficial explanation in:
>>>>>>>
>>>>>>> http://arjan-tijms.omnifaces.org/2015/07/jsf-23-new-feature-
>>>>>>> registrable.html
>>>>>>>
>>>>>>> The feature is ok from a functional perspective, it has sense,
>>>>>>>
>>>>>>
>>>>>> Good! :)
>>>>>>
>>>>>>
>>>>>>
>>>>>>> It means if UIData.getValue() has a value with type MyCollection,
>>>>>>> the value
>>>>>>> will be wrapped in a MyCollectionModel instance. This resembles
>>>>>>> "targetClass" for Converter instances.
>>>>>>>
>>>>>>
>>>>>> True, that kinda was the inspiration for the particular
>>>>>> implementation of this feature request.
>>>>>>
>>>>>>
>>>>>>
>>>>>>> But in JSF, there is an Aplication class where you can register
>>>>>>> Converter
>>>>>>> instances to apply for an specific "targetClass" and so on. But
>>>>>>> there is
>>>>>>> nothing for DataModel.
>>>>>>>
>>>>>>
>>>>>> It basically happens fully via CDI now. Either user provided with the
>>>>>> @FacesDataModel annotation, or programmatically by adding your own
>>>>>> annotated classes and/or Bean<T> instances using the CDI API (in an CDI
>>>>>> extension).
>>>>>>
>>>>>>
>>>>>>
>>>>>>> no new description in UIData.getDataModel(), nothing.
>>>>>>>
>>>>>>
>>>>>> That's a good point, I'll look at providing something of a
>>>>>> description there right away.
>>>>>>
>>>>>> Thanks again Leo!
>>>>>>
>>>>>> Kind regards,
>>>>>> Arjan Tijms
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>