[ 
https://issues.apache.org/jira/browse/MYFACES-1820?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12792071#action_12792071
 ] 

Simon Kitching commented on MYFACES-1820:
-----------------------------------------

For FacesContext subclasses, this issue could originally be triggered by:
[1] create class CustomFacesContextFactory which returns a new 
CustomFacesContext instance
[2] define class CustomFacesContext, and have its constructor call 
FacesContext.setCurrentInstance(this)
     (just as the default FacesContextImpl class does)
[3] configure the faces-config.xml so that this factory is used.
then accessing any standard jsf page. The faces contexts were created, and then 
when an EL expression is found in the page, JSF called 
FacesContext.getCurrentInstance().getELContext() and an infinite loop 
immediately occured.

I committed the attached patch for the FacesContext class quite a while ago; 
see r634007. This is a *partial* fix, in that it does avoid infinite loops. 
However it does not properly delegate to the "wrapped" instance; instead, it 
delegates directly to the "last" instance in the chain of wrapped classes.

The issue is not closed because
(a) the solution is not right when multiple layers of wrappers exist, and
(b) the same issue exists for JSF "decorator" classes other than FacesContext.

It's been quite a while since I wrote this issue, so I can't remember exactly 
which other classes have problems. But they are those classes that may want to 
delegate to an "underlying" implementation (ie implement the decorator 
pattern), but JSF provides no way to locate that underlying implementation. I 
think they include:
* Lifecycle
* RenderKit
* NavigationHandler?

> Infinite loop can occur when custom FacesContext subclass compiled against 
> JSF1.1 but used with JSF1.2
> ------------------------------------------------------------------------------------------------------
>
>                 Key: MYFACES-1820
>                 URL: https://issues.apache.org/jira/browse/MYFACES-1820
>             Project: MyFaces Core
>          Issue Type: Bug
>          Components: JSR-252
>    Affects Versions: 1.2.2
>            Reporter: Simon Kitching
>         Attachments: FacesContext.patch.txt, patch-1820.txt
>
>
> The problem is method FacesContext.getELContext. JSF1.2 added a method to 
> this base class that was not there in JSF1.1. This makes life difficult for 
> existing JSF1.1 code that already subclasses that class.
> A default concrete implementation needs to exist, in order not to break 
> existing JSF1.1 code, but (a) the current one gets it wrong, and (b) defining 
> a correct one is difficult (impossible?)
> (1) Stan Silvert initially defined this method like this:
> // The following concrete method was added for JSF 1.2.  
> // It supplies a default 
> // implementation that throws UnsupportedOperationException.  
> // This allows old FacesContext implementations to still work.
> public ELContext getELContext() {
>     throw new UnsupportedOperationException();
> }
> (2) Dennis Byrne changed it to its current form:
> public ELContext getELContext() {
>   FacesContext ctx = getCurrentInstance();
>   if (ctx == null)
>       throw new NullPointerException(FacesContext.class.getName());
>   ELContext elctx = ctx.getELContext();
>   if (elctx == null)
>       throw new UnsupportedOperationException();
>   return elctx;
> }
> However (2) assumes that custom subclasses never set themselves as the 
> current instance, instead only ever *delegating* to the "real" instance.
> If someone's custom subclass of FacesContext ever calls 
> setCurrentInstance(this), then an infinite loop will occur here.
> And in fact, this is just what we get:
> java.lang.StackOverflowError
>       at java.lang.ThreadLocal$ThreadLocalMap.getEntry(ThreadLocal.java:357)
>       at java.lang.ThreadLocal$ThreadLocalMap.access$000(ThreadLocal.java:242)
>       at java.lang.ThreadLocal.get(ThreadLocal.java:127)
>       at 
> javax.faces.context.FacesContext.getCurrentInstance(FacesContext.java:98)
>       at javax.faces.context.FacesContext.getELContext(FacesContext.java:35)
>       at javax.faces.context.FacesContext.getELContext(FacesContext.java:40)
>       at javax.faces.context.FacesContext.getELContext(FacesContext.java:40)
>       at javax.faces.context.FacesContext.getELContext(FacesContext.java:40)
>       at javax.faces.context.FacesContext.getELContext(FacesContext.java:40)
>       at javax.faces.context.FacesContext.getELContext(FacesContext.java:40)
>       at javax.faces.context.FacesContext.getELContext(FacesContext.java:40)
>       at javax.faces.context.FacesContext.getELContext(FacesContext.java:40)
>       at javax.faces.context.FacesContext.getELContext(FacesContext.java:40)
>       at javax.faces.context.FacesContext.getELContext(FacesContext.java:40)
>       at javax.faces.context.FacesContext.getELContext(FacesContext.java:40)

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to