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

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

From: Michael Müller <michael.mueller_at_mueller-bruehl.de>
Date: Mon, 06 Oct 2014 22:08:26 +0200

Hi Manfred,

I assume this shall work with any other context too? I'm thinking
especial of a custom defined context.

And thinking of @SessionScoped or beans with a longer lifecycle: During
a session I might call a non-Faces Servlet, for example an upload bean
(although JSF offers upload, I prefer a JavaScript controlled upload by
XMLHttpRequest or iFrame to show a progress bar, cancel button, and
more). And I need to access some other backing beans. It would be much
easier to perform such an access if it would be possible to inject a
FacesContext in such a Servlet. Although there is no call to the Faces
Servlet, I guess it would be possible to inject the same context as
available for a @SessionScoped bean.

Herzliche Grüße - Best Regards,

Michael Müller

Web Development with Java and JSF: https://leanpub.com/jsf
Am 06.10.2014 17:10, schrieb manfred riem:
> 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)?
>
> 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
>> <mailto: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 <mailto: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
>>> <mailto:arjan.tijms_at_gmail.com>>:
>>>> Hi,
>>>>
>>>> On Thu, Sep 25, 2014 at 4:32 PM, Edward Burns
>>>> <edward.burns_at_oracle.com <mailto: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
>>
>>
>