myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Leonardo Uribe (JIRA)" <...@myfaces.apache.org>
Subject [jira] Commented: (MYFACES-2995) Make method of determinine app context in FactoryFinder pluggable
Date Sat, 19 Feb 2011 21:50:38 GMT

    [ 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

        

Mime
View raw message