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

[jsr344-experts] Re: 1012 ExternalContext.getApplicationContextPath()

From: Neil Griffin <neil.griffin_at_portletfaces.org>
Date: Tue, 18 Dec 2012 16:56:58 -0500

Comments inline below..

On Dec 18, 2012, at 3:19 PM, Leonardo Uribe <lu4242_at_gmail.com> wrote:

> Hi
>
> 2012/12/18 Neil Griffin <neil.griffin_at_portletfaces.org>:
>> Hi Ed,
>>
>> Regarding issue 1012 [1], the JSF 2.2 JavaDocs expose a new method on
>> ExternalContext named getApplicationContextPath() which has the following
>> requirements:
>>
>> * <p class="changed_added_2_2"><em>Servlet:</em>
>> * Return the result of calling
>> * <code>getContextPath()</code> on the
>> * <code>ServletContext</code> instance for this application. It is
>> * valid to call this method during application startup or shutdown.</p>
>>
>> Since FacesContext.getCurrentInstance() is a ThreadLocal singleton bound to
>> the request thread, it is not possible to call
>> FacesContext.getCurrentInstance().getExternalContext() during application
>> startup or shutdown.
>>
>
> In my understanding, allow FacesContext.getCurrentInstance() during application
> startup/shutdown was added since JSF 2.0, at least in MyFaces, but I'm pretty
> sure about the same for Mojarra, because it was discussed long time ago.
>
> In MyFaces there is an interface called
> org.apache.myfaces.webapp.FacesInitializer with these methods:
>
> void initFaces(ServletContext servletContext);
> void destroyFaces(ServletContext servletContext);
> FacesContext initStartupFacesContext(ServletContext servletContext);
> void destroyStartupFacesContext(FacesContext facesContext);
> FacesContext initShutdownFacesContext(ServletContext servletContext);
> void destroyShutdownFacesContext(FacesContext facesContext);
>
> You can set the initializer using a web config param called:
> org.apache.myfaces.FACES_INITIALIZER
>
> This interface is very helpful when you need some special initialization steps.
> In MyFaces there are 3 initializers:
>
> org.apache.myfaces.webapp.Jsp20FacesInitializer
> org.apache.myfaces.webapp.Jsp21FacesInitializer
> org.apache.myfaces.webapp.FaceletsInitilializer (only facelets, disable jsp)
>
> I know for user application it is better to use a JSF application
> scope bean with
> eager=true and use @PostConstruct and @PreDestroy annotations, but in portlet
> case a similar interface could be useful, obviously doing some changes
> to make it more neutral interface
>
> Note there is a difference between startup/shutdown FacesContext and the one
> used for requests in JSF, but for now that startup/shutdown FacesContext is an
> implementation detail, and in some way bound to a servlet container because
> to get the "context" of the application it is necessary to retrieve a
> ServletContext instance, usually from a Listener
> (see org.apache.myfaces.webapp.StartupServletContextListener).
>
>> Also, the Portlet API does not provide access to the underlying
>> ServletContext. I suppose that the best we could do in a portlet environment
>> would be to register a ServletContextListener and remember the
>> ServletContext instance for later reference.
>>
>> When you get a chance, could you elaborate on what made it necessary to add
>> the getApplicationContextPath() feature?
>>
>
> That method shows the missing piece of the puzzle. In portlet case you
> want to override
> that method, but since startup/shutdown FacesContext/ExternalContext are
> implementation details, you cannot pass the PortletContext or
> PortletConfig or what's
> necessary to make it work.
>
> regards,
>
> Leonardo Uribe

@Leonardo: Thanks for the feedback regarding MyFaces. I see that MyFaces has a StartupFacesContextImpl class and Mojarra has an InitFacesContext class. And... each of these have their own "startup" version of ExternalContext. Additionally, Section 6.1.4 of the Spec says the following about FacesContext.getExternalContext():

"The default implementation must return a valid value when this method is called during startup time. See the javadocs for this method for the complete specification."

@Leonardo/_at_Ed:

Perhaps it would be more straightforward (from the API perspective) if FacesContextFactory and/or ExternalContextFactory had methods for acquiring startup instances?

If not, then given the current startup design of MyFaces and Mojarra, is it safe to assume that the portlet bridge implementation of ExternalContext.getApplicationContextPath() would only be called during a request?

Thanks guys,

-- Neil

>
>> Thanks,
>>
>> Neil
>>
>> [1] http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1012
>>