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

[jsr372-experts] Re: [PROPOSAL] CDI integration for UIComponent instances in JSF 2.3

From: Leonardo Uribe <leonardo.uribe_at_irian.at>
Date: Fri, 23 Dec 2016 18:34:11 -0500

Hi

Attached to this mail there is the code of the feature.

It is a maven app with two CDI extensions and some examples that shows how
it works.
This code relies on Search Expression API, so once that code is added you
can just
easily copy/paste to Mojarra.

It is still pending the javadoc of @ResolveComponent (maybe a better name
is
@ResolveFacesComponent?).

Some working examples

    @Inject
    @ResolveComponent("@root")
    private UIViewRoot viewRoot;

    @Inject
    @ResolveComponent("updateButton")
    private HtmlCommandButton button;

    @Inject
    @ResolveComponent("mainForm:out")
    private HtmlOutputText out;

I'll send the javadoc in January. Merry Christmas and a Happy New Year!.

regards,

Leonardo Uribe


2016-12-23 13:30 GMT-05:00 Leonardo Uribe <leonardo.uribe_at_irian.at>:

> Hi Manfred
>
> Thanks for accept this change.
>
> Since this is a new feature, the only change in the API or spec is add
> javax.faces.annotation.ResolveComponent annotation. I saw these
> two issues created in the issue tracker:
>
> https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1283
> Allow for injection on UIComponent, Converter and Validator
> https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1316
> Support @Inject on JSF artifacts
>
> Fortunately this change is a new feature that does not change
> other parts in the code, so it is just add some files and
> include the two extensions in
> META-INF/services/javax.enterprise.inject.spi.Extension
>
> I'll send you the files with the implementation and the
> javadoc, which is 95% ready. I would like to attach the files
> in the issue tracker but I do not have permissions to
> do that.
>
> The other option is ask Thomas Andraschko to include this,
> since he is working to include Search Expression API, which is
> related to this issue (that algorithm resolves the expression
> in @ResolveComponent, so this is another use case for that API).
>
> @Thomas: have you already committed the changes proposed
> for Search Expression API in Mojarra or it is still work in
> progress?
>
> regards,
>
> Leonardo Uribe
>
>
>
> 2016-12-23 11:19 GMT-05:00 manfred riem <manfred.riem_at_oracle.com>:
>
>> Hi Leonardo,
>>
>> You can do the work as a pull request. We will need the JavaDocs
>> and the Mojarra implementation. If you're going to submit a pull
>> request, you'll have to include that and more.
>>
>> As for the JavaDocs, make sure to include full changebar attribution,
>> as documented at [1].
>>
>> The changes must be hidden behind a context-param and the new
>> behaviour must be only enabled if the context-param is set to true.
>>
>> You can take a look at the work Ed just did for
>> JAVASERVERFACES_SPEC_PUBLIC-1433 for a very fresh example.
>>
>> The work must include a TDD test. Again, look at issue 1433 for a guide.
>>
>> The change must not break any existing tests. We're willing to accept
>> this, but time is VERY short. We need to have all the spec related
>> content, including JavaDocs, in final form by 2017-01-12.
>>
>> We would need all the implementation work done by 2017-01-27.
>> Ideally, sooner is better because it gives us time to suss out any
>> problems.
>>
>> Thanks!
>>
>> Kind regards,
>> Manfred Riem
>>
>> [1]https://glassfish.java.net/wiki-archive/JavaServerFacesRI
>> .html#JavaServerFacesRI-HowdoImakesurethatchangestothespecha
>> vethecorrectversionchangebarattributions%3F
>>
>>
>> On 12/21/16, 5:10 PM, Leonardo Uribe wrote:
>>
>>> Hi
>>>
>>> I have some good news to tell.
>>>
>>> After some attempts and using Arjan trick in Omnifaces, and based on the
>>> previous discussion I was able to code a consistent solution using a
>>> CDI centric approach. I made this example work:
>>>
>>> @Named
>>> @SessionScoped
>>> public class UserSessionBean implements Serializable
>>> {
>>>
>>> @Inject
>>> @ResolveComponent(value="updateButton")
>>> private HtmlCommandButton button;
>>>
>>> // ...
>>> }
>>>
>>> This change things drastically, from an scenario where this cannot be
>>> included to other where we could do it once for all.
>>>
>>> Please not the trick has two requeriments to be considered succesful:
>>>
>>> - The injected object must be the final component class
>>> (HtmlCommandButton)
>>> - The injected object must be a normal scope proxy that avoids
>>> inteference with JSF state saving.
>>>
>>> And the solution proposed comply with these two requeriments.
>>>
>>> I'll describe how the solution works, because I considered this
>>> relevant to be included in JSF 2.3 scope. The code are two CDI
>>> extensions:
>>> one for the internal @ViewTransientScope and the other for
>>> @ResolveComponent. The spec changes are just include the annotation:
>>>
>>> /**
>>> *
>>> */
>>> @Qualifier
>>> @Retention(value=RetentionPolicy.RUNTIME)
>>> @Target(value={ElementType.TYPE, ElementType.METHOD,
>>> ElementType.PARAMETER, ElementType.FIELD})
>>> public @interface ResolveComponent
>>> {
>>> public String value() default "";
>>> }
>>>
>>> To be able to inject different component instances, we need to generate
>>> one producer per component class and search expression.
>>>
>>> The code aims to found injections of @ResolveComponent and collect the
>>> component classes:
>>>
>>> public <T> void collect(@Observes ProcessManagedBean<T> event)
>>>
>>> and then create one dynamic producer per component class and
>>> expression in:
>>>
>>> public void afterBean(
>>> @Observes AfterBeanDiscovery afterBeanDiscovery,
>>> BeanManager beanManager)
>>>
>>> The producer is a class implementing Bean<UIComponent> with to
>>> important things:
>>>
>>> - getBeanClass() returns the component class we need to instantiate the
>>> proxy.
>>> - getScope() returns @ViewTransientScope, which is an internal
>>> annotation that relies on UIViewRoot transient map used to control
>>> the lifecycle of the proxy instances.
>>> - The bean should hold the "expression" or "id" that this proxy
>>> depends, because when the proxy is resolved, the access to the
>>> InjectionPoint is lost.
>>>
>>> The last thing is use JSF 2.3 Search Expression API to define
>>> expressions or id chains that resolve the right component
>>> instance, like it was mentioned previously.
>>>
>>> I also discovered that fix "binding" has another problem that prevent
>>> it to be fixed. The problem is proxy classes does not have information
>>> about injection points when they are resolved and you can't add
>>> producer instances at runtime or pass the necessary information to
>>> locate the component to the proxy.
>>>
>>> So, in this moment the CDI centric solution is the one that looks
>>> viable to be included officially in JSF 2.3.
>>>
>>> WDYT? Could this solution be included in JSF 2.3? What needs to be
>>> done to include it? Do you support this feature?
>>>
>>> regards,
>>>
>>> Leonardo Uribe
>>>
>>>
>