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

[jsr372-experts] Re: [527-InjectFacesContext] Support and review

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Mon, 6 Oct 2014 17:36:43 +0200

Hi

On Mon, Oct 6, 2014 at 5:10 PM, manfred riem <manfred.riem_at_oracle.com> wrote:
> Hi Arjan,
>
> Can you verify if the proxying works properly by writing some tests that
> exercise the injection of the FacesContext using @Inject into the managed
> beans using following scope types (@RequestScoped, @SessionScoped,
> @FlowScoped, @ViewScoped, @ApplicationScoped)?

I'll take a look. May be a little challenging to explicitly test for
"proxy or not", but let's see if I can get up with something.

What shall I use as the implementation for the injection itself?
Latest Mojarra 2.3 source?

Btw, there was a potential issue with @Produces not being picked up by
the jars that are installed inside the container (like is typical for
JSF). Using a CDI extension with some kind of dynamic producer could
be an option to work around that.

Did you looked into that?

Kind regards,
Arjan



>
> If we can verify that all are working as expected I think from a developer
> perspective this is enough. For any of the other corner use cases I think we
> should push back for now, unless someone wants to spearhead the work on
> that. Any takers?
>
> Thanks!
> Manfred
>
>
> On 9/25/14, 4:56 PM, arjan tijms wrote:
>
> Hi,
>
> On Thu, Sep 25, 2014 at 6:58 PM, Neil Griffin
> <neil.griffin_at_portletfaces.org> wrote:
>>
>> The JSF Portlet Bridge will make beans annotated with
>> javax.faces.bean.RequestScoped survive from the ACTION_PHASE to the
>> RENDER_PHASE.
>>
>> But CDI does not do that. If a JSF portlet developer annotates a bean with
>> javax.enterprise.context.RequestScoped, then CDI creates a new bean in both
>> the ACTION_PHASE and RENDER_PHASE.
>
>
> I have to admit I know almost nothing about Portlets, but if I understand
> correctly this is thus a general problem with
> javax.enterprise.context.RequestScoped and Portlets, and not specifically
> with injecting a request scoped FacesContext, right?
>
> But in this case would it really matter? If a single CDI request scope does
> not survive beyond the Portlet action phase and into the render phase, then
> there would simply be one additional call to FacesContext#getCurrentInstance
> if the proxy is referenced again in the render phase, right? This then grabs
> the current FacesContext according to the existing JSF rules and all should
> be right again. Or am I missing something obvious?
>
>>
>> If there is a successor to JSR 329, then one of the requirements for that
>> new JSR *might* be to re-define the behavior of
>> javax.enterprise.context.RequestScoped.
>
>
> Just wondering, but isn't JSR 329 specifically designed for interoperability
> with JSF 1.2 only?
>
> Kind regards,
> Arjan
>
>
>>
>>
>> On Sep 25, 2014, at 12:36 PM, Leonardo Uribe <leonardo.uribe_at_irian.at>
>> wrote:
>>
>> Hi
>>
>> I know that the trick using @RequestScoped works, but
>> Is there a 1-1 relationship between FacesContext lifecycle
>> and the request lifecycle? That works fine on servlets but
>> it doesn't on portlets (action request / render request).
>>
>> It is possible to imagine other scenarios where this
>> assumption just fail. In my opinion, we should take the
>> long route, create a CDI scope and use that scope to
>> store the producer, so it get the right instance. After all
>> JSF should be in control of FacesContext lifecycle.
>>
>> regards,
>>
>> Leonardo Uribe
>>
>>
>> 2014-09-25 11:02 GMT-05:00 arjan tijms <arjan.tijms_at_gmail.com>:
>>
>> Hi,
>>
>> On Thu, Sep 25, 2014 at 4:32 PM, Edward Burns <edward.burns_at_oracle.com>
>> wrote:
>>
>> Arjan, can you take the action item to investigate this and report back
>> to the group? Such investigations and reports are the bread and butter
>> of expert group membership and really add significant value because the
>> results the produce are so actionable.
>>
>>
>> I took a quick look, and the results are rather interesting.
>>
>> First of all, the feature is described here:
>>
>> http://docs.jboss.org/seam/3/servlet/latest/reference/en-US/html/injectablerefs.html#injectablerefs.http_servlet_request
>>
>> The producer was created by CDI wizards Dan Allen and Nicklas
>> Karlsson, and for the HttpServletRequest it looks as follows:
>>
>> @Produces
>> @Typed(HttpServletRequest.class)
>> @RequestScoped
>> protected HttpServletRequest getHttpServletRequest() {
>> return holder.getHttpServletRequest();
>> }
>>
>> See:
>> http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.jboss.seam.servlet/seam-servlet/3.1.0.Beta2/org/jboss/seam/servlet/http/ImplicitHttpServletObjectsProducer.java?av=f
>>
>> The holder is an application scoped bean, which has as its main goal
>> to collect and hold on to among others the HttpServletRequest via a
>> thread local. Collection happens via a CDI event and the listeners
>> stores the request object into TLS via a wrapper. Abbreviated it's:
>>
>> protected void requestInitialized(@Observes @Initialized final
>> InternalServletRequestEvent e) {
>> ServletRequest req = e.getServletRequest();
>> // code omitted
>> requestCtx.set(new HttpServletRequestContext(req));
>> }
>>
>> See:
>> http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.jboss.seam.servlet/seam-servlet/3.1.0.Beta2/org/jboss/seam/servlet/event/ImplicitServletObjectsHolder.java#70
>>
>> But the wrapper doesn't play a role in injection, since when the
>> producer asks the holder for the request instance, it's unwrapped
>> again. Abbreviated it's:
>>
>> public HttpServletRequest getHttpServletRequest() {
>> // code omitted
>> return
>> HttpServletRequestContext.class.cast(requestCtx.get()).getRequest();
>> }
>>
>> See:
>> http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.jboss.seam.servlet/seam-servlet/3.1.0.Beta2/org/jboss/seam/servlet/event/ImplicitServletObjectsHolder.java#128
>>
>> So there's not a lot of magic going at all. The key seems to be that
>> the producer itself is @RequestScoped, but the instance it produces
>> doesn't seem to be a request scoped wrapper bean at all, just the
>> normal instance. I do wonder a bit why they choose TLS storage instead
>> of a request scoped bean, but that's beside the issue here.
>>
>> As JSF already stores the FacesContext in TLS, the entire holder
>> construct isn't needed and seemingly the producer would only need to
>> be annotated with @RequestScoped.
>>
>> Kind regards,
>> Arjan
>>
>>
>