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: Sun, 8 Jan 2017 16:50:39 -0500

Hi

Attached to this mail there is the javadoc suggested for @ResolveComponent.

/**
 * This annotation injects a CDI proxy that points through a JSF 2.3 search
expression to a valid JSF component
 * instance.
 *
 * The implementation must provide an implementation of
javax.enterprise.inject.spi.Extension that implements the
 * semantics such that proxy classes with this annotation are created when
the bean instance is injected, and
 * de-allocated when the bean is discarded. The proxy instances must be
bound to a normal scope that is active as
 * long as the current view is available in the current faces request. The
instances can be stored in the UIViewRoot
 * view transient map.
 *
 * When a method of the proxy is invoked in the CDI bean, the proxy
instance must use the search expression to locate
 * the real UIComponent instance in the component tree using a call to
SearchExpressionHandler.resolveComponent(...),
 * passing as hint SearchExpressionHint.SKIP_VIRTUAL_COMPONENTS. The
component that will be used as a source
 * reference to locate the component will be the component returned by
UIComponent.getCurrentComponent(...) at the
 * moment the method is called, so the user is responsible to provide an
expression that can be valid at any time
 * the proxy component is used.
 *
 * @since 2.3
 */



I think it describes in a clear way how the annotation works and their
limitations.

The only thing left is a review from you guys, compare this with what you
had in mind about this and if the solution is good enough or not.

I'll keep an eye on this, this is one of my favorite features for 2.3, so I
hope it can be included.

regards,

Leonardo Uribe


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

> 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
>>>>
>>>>
>>
>