[
https://issues.apache.org/jira/browse/MYFACES-2995?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12996886#comment-12996886
]
Leonardo Uribe commented on MYFACES-2995:
-----------------------------------------
I thought a lot about FactoryFinder and how we can "extend" it. I'll do a
resume, describing the problem in detail and providing some alternatives. This
could be a little bit redundant, but it is necessary to gain a better
understanding about what's going on and the direction to take.
FactoryFinder is a class with three methods:
public final class FactoryFinder
{
public static Object getFactory(String factoryName) throws FacesException
{...}
public static void setFactory(String factoryName, String implName) {...}
public static void releaseFactories() throws FacesException {...}
}
The javadoc describe the intention of FactoryFinder class:
"... FactoryFinder implements the standard discovery algorithm for all factory
objects specified in the JavaServer Faces APIs. For a given factory class name,
a corresponding implementation class is searched for based on the following
algorithm...."
On the javadoc there is more information from the point of view of the author
(classloading stuff and so on), but just ignore it for a moment, because it
only makes things confusing.
In few words, this class allows to find JSF factory classes. The necessary
information to create factory instances is loaded on initialization time, but
which locations contains such information (for more information see JSF 2.0
spec section 11.4.2) (we are only interested in jsf factories initialization
information) ?
- Look factories on META-INF/services/[factoryClassName]
- Look META-INF/faces-config.xml or META-INF/[prefix].faces-config.xml
- Look the files pointed by javax.faces.CONFIG_FILES web config param (note
WEB-INF/web.xml is taken into consideration)
- Look the applicationFacesConfig on WEB-INF/faces-config.xml
Based on the previous facts, the first conclusion to take into account arise:
Configuration information is gathered per "web context". What is a "web
context"? In simple terms, is the "space" where a web application is deployed.
Let's suppose an EAR file with two WAR files: a.war and b.war. Both contains
different "web applications" and when are deployed has different "web context",
so both can provide different factory configuration, because both has different
WEB-INF/web.xml and WEB-INF/faces-config.xml files.
Now, given a request, how the web container identify a "web context"? At start,
it receives the request information and based on that it decides which web
application should process it. After that, it assign to a thread from is thread
pool to be processed and the control is passed to the proper filters/servlets.
So, if we don't have a servlet context/portlet context/whatever context, how to
identify a "web context"? The answer is using the thread, but the one who knows
how to do that is the web container, not the jsf implementation.
The existing problem is caused by a "shortcut" taken to make things easier.
Instead use the current "thread", it is taken as advantage the fact that each
web application deployed has a different classloader. That is true for a lot of
application servers, so the current implementation of FactoryFinder is based on
that fact too and has worked well since the beginning.
Now let's examine in detail how a "single classloader per EAR" option could
work. If the EAR has two WAR files (a.war and b.war), we have two web context,
and the initialization code is executed twice. When all FactoryFinder methods
are called?
- FactoryFinder.setFactory is called on initialization
- FactoryFinder.releaseFactories is called on shutdown
- FactoryFinder.getFactory is called after initialization configuration is done
but before shutdown call to FactoryFinder.setFactory .
Remember all methods of FactoryFinder are static.
One possible solution could be:
1. Create a class called FactoryFinderProvider, that has the same three method
but in a non static version.
2. A singleton component is provided that holds the information of the
FactoryFinderProviderFactory. This one works per classloader, so the singleton
is implemented using an static variable. To configure it, the static method
should be called when the "classloader realm" is initialized, before any web
context is started (the WAR is deployed). Usually the EAR is started as a
single entity, so this should occur when the EAR starts, but before the WAR
files are started (or the web context are created). The singleton will be
responsible to decide which FactoryFinderProvider should be used, based on the
current thread information.
3. Add utility methods to retrieve the required objects and call the methods
using reflection from javax.faces.FactoryFinder
I provided a patch a patch for this one
(MYFACES-2995-FactoryFinderProvider-1.patch)
If no objections I'll commit this code soon.
> Make method of determinine app context in FactoryFinder pluggable
> -----------------------------------------------------------------
>
> Key: MYFACES-2995
> URL: https://issues.apache.org/jira/browse/MYFACES-2995
> Project: MyFaces Core
> Issue Type: Improvement
> Components: SPI
> Affects Versions: 2.0.3-SNAPSHOT
> Reporter: David Jencks
> Attachments: MYFACES-2995-FactoryFinderProvider-1.patch,
> MYFACES-2995.patch
>
>
> As discussed on dev list.... geronimo would like to explicitly mark component
> boundaries rather than relying on the TCCL changing.
--
This message is automatically generated by JIRA.
-
For more information on JIRA, see: http://www.atlassian.com/software/jira