On Dec 18, 2012, at 5:50 PM, Leonardo Uribe <lu4242_at_gmail.com> wrote:
> 2012/12/18 Neil Griffin <neil.griffin_at_portletfaces.org>:
>> 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?
>>
>
> Probably, but probably that requires create wrapper classes for
> FacesContextFactory and ExternalContextFactory.
Unless I misunderstand, we might be able to just rely on the implied factory wrapping feature of FacesContextFactory and ExternalContextFactory. Check out the constructors in the following classes:
https://github.com/liferay/liferay-faces/blob/master/test/bridge-tck-compat/src/main/java/com/liferay/faces/bridge/tck/context/FacesContextFactoryTCKImpl.java
https://github.com/liferay/liferay-faces/blob/master/bridge-impl/src/main/java/com/liferay/faces/bridge/context/ExternalContextFactoryImpl.java
> Another option is include a StartupFacesContextFactory / StartupExternalContextFactory.
> MyFaces makes difference over startup/shutdown just for logging purposes, but
> the instances is the same. Note the difference between a FacesContext created
> on startup is that there is no request, so all related methods should throw
> UnsupportedOperationException, but the ones related to config or context should
> work without problem.
>
>> 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?
>>
>
> It does not look nice, but I think there is no need to call that method on
> startup/shutdown more than use it in the log.
>
> regards,
>
> Leonardo
>
>> Thanks guys,
>>
>> -- Neil
>>
>>
>> Thanks,
>>
>> Neil
>>
>> [1] http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1012
>>
>>