[
https://issues.apache.org/jira/browse/MYFACES-4250?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16741833#comment-16741833
]
Simon Geard commented on MYFACES-4250:
--------------------------------------
Unfortunately not. I spent a week or so beating my head against this issue
before logging this bug, and if you'd asked me at the time, I could have
provided the details you're looking for. But that was many months ago now, and
both my modified code, and any recollection of the details are long gone... we
gave up on using annotations and settled for registering everything in
faces-config.xml...
But the theory is simple enough. Look at the changes made in the following
commit, addressing MYFACES-3830...
[https://github.com/javaeekickoff/myfaces/commit/43a595f55aa5289b0c362de660da8aeeb8e1466e#diff-a5e264e22fed64c66313e5f64e749e39]
The code temporarily creates an instance of
LoadComponentTagDeclarationFacesContextWrapper, to temporarily wrap the real
FacesContext, and calls restoreCurrentFacesContext to release it once complete.
But I found that if an ELContext was created during this period, it ended up
holding a reference to the wrapper FacesContext, and the dummy view root, and
continued to use this instead of the real context and view root.
As I said, I can't remember specifics, because this was a long time ago. But
looking at the code again, consider FacesContextImplBase.getELContext - it
constructs a new FacesELContext instance, passing in the
FacesContext.getCurrentInstance(), which is currently the unwanted wrapper.
That FacesELContext instance lasts as long as the FacesContextImplBase which
created it does - but it's pointing to what's supposed to be a very short-lived
wrapper around that context.
As such, my best recollection is that my patch did the same thing as the
FacesELContext constructor does... that is, it calls
putContext(FacesContext.class, facesContext) on the ELContext, replacing the
unwanted wrapper with the real context. Not sure if that's a good fix or not,
but it *did* solve the problem at time.
Note that if my memory is correct about the problem, it only happens if the
ELContext hadn't already been created before the call to
FaceletsCompilerSupport.loadLibraries *and* something calls getELContext during
the period where the wrapper context is the 'current' context, before the
finally block where the thing gets removed. So that might explain why it's
difficult to replicate, if you're not meeting those conditions...
> NullPointerException triggered as consequence of
> FaceletsCompilerSupport.loadLibraries
> --------------------------------------------------------------------------------------
>
> Key: MYFACES-4250
> URL: https://issues.apache.org/jira/browse/MYFACES-4250
> Project: MyFaces Core
> Issue Type: Bug
> Affects Versions: 2.2.12, 2.3.1
> Reporter: Simon Geard
> Priority: Major
>
> I've recently been investigating a problem with our product, whereby the
> first time a JSF-based screen loads, it fails with the following error in the
> logs:
>
> {{Caused By: java.lang.NullPointerException}}
> {{ at
> org.apache.myfaces.view.facelets.el.FaceletStateValueExpression.getWrapped(FaceletStateValueExpression.java:86)}}
> {{ at
> org.apache.myfaces.view.facelets.el.FaceletStateValueExpression.getValue(FaceletStateValueExpression.java:118)}}
> {{ at com.sun.el.parser.AstIdentifier.getValue(AstIdentifier.java:99)}}
> {{ at com.sun.el.parser.AstValue.getValue(AstValue.java:179)}}
> {{ at
> com.sun.el.parser.AstDeferredExpression.getValue(AstDeferredExpression.java:63)}}
>
> After some effort debugging, I found that the immediate cause of the NPE is
> that on the first line of the getWrapped(ELContext) method, the FacesContext
> is obtained from the ELContext, rather than by calling
> FacesContext.getCurrentInstance. The FacesContext obtained this way is not
> the same FacesContext that's being used elsewhere in the stacktrace, and the
> UIViewRoot it supplies is likewise not the same one used elsewhere... this
> incorrect view root does not contain the facelet state instance, so the 'map'
> variable is null, causing the exception.
>
> Digging further, I found that the source of the incorrect FacesContext and
> UIViewRoot is the FaceletsCompilerSupport class, and that my problem relates
> to the bug MYFACES-3830. The short version is that for the purpose of
> figuring out all the annotation driven components and renderers,
> FaceletsCompilerSupport creates a dummy FacesContext wrapping the real one
> (and view root), which it de-registers once it's done.
> However, some of the code which uses that FacesContext asks for the
> ELContext, which causes an ELContext to be created - and the ELContext holds
> a reference to the FacesContext as at the time it was created, which is the
> unwanted one from FaceletsCompilerSupport.
>
> I can "fix" the problem for my purposes by patching the
> LoadComponentTagDeclarationFacesContextWrapper to push the correct
> FacesContext into the ELContext during teardown (the
> restoreCurrentFacesContext method), but I'm not sure if that's a good
> production fix...
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)