Bug 900561 (JBPAPP6-896)
| Summary: | FacesContext.getCurrentInstance returns external context from a different deployment during application startup | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Product: | [JBoss] JBoss Enterprise Application Platform 6 | Reporter: | Marek Schmidt <maschmid> | ||||||||
| Component: | Web | Assignee: | Stan Silvert <ssilvert> | ||||||||
| Status: | CLOSED CURRENTRELEASE | QA Contact: | |||||||||
| Severity: | high | Docs Contact: | |||||||||
| Priority: | high | ||||||||||
| Version: | 6.0.0 | CC: | abn, maschmid, mnovotny, sgilda, ssilvert, twells | ||||||||
| Target Milestone: | --- | ||||||||||
| Target Release: | EAP 6.0.1 | ||||||||||
| Hardware: | Unspecified | ||||||||||
| OS: | Unspecified | ||||||||||
| URL: | http://jira.jboss.org/jira/browse/JBPAPP6-896 | ||||||||||
| Whiteboard: | eap601candidate | ||||||||||
| Fixed In Version: | Doc Type: | Bug Fix | |||||||||
| Doc Text: | Story Points: | --- | |||||||||
| Clone Of: | Environment: |
EAP 6.0.0.CR1, JDK 1.6.0_30
|
|||||||||
| Last Closed: | 2013-02-21 11:18:06 UTC | Type: | Bug | ||||||||
| Regression: | --- | Mount Type: | --- | ||||||||
| Documentation: | --- | CRM: | |||||||||
| Verified Versions: | Category: | --- | |||||||||
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||||||
| Cloudforms Team: | --- | Target Upstream Version: | |||||||||
| Embargoed: | |||||||||||
| Attachments: |
|
||||||||||
|
Description
Marek Schmidt
2012-05-31 09:12:54 UTC
Attachment: Added: server.log Interesting log excerpts from the second deployment (Seam Booking) (notice the "XXX: facesContext Seam Blog Example" lines)
{noformat}
...
10:24:25,749 INFO [org.jboss.as.repository] (management-handler-thread - 2) JBAS014900: Content added at location /home/maschmid/testing/eap6/jboss-eap-6.0.0.CR1/jboss-eap-6.0/standalone/data/content/50/f1033a06466949685e1c3351994ffa193b2e84/content
10:24:25,754 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) JBAS015876: Starting deployment of "seam-booking.ear"
10:24:26,037 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) JBAS015876: Starting deployment of "booking-ejb.jar"
10:24:26,037 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) JBAS015876: Starting deployment of "jboss-seam.jar"
10:24:26,038 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) JBAS015876: Starting deployment of "booking-web.war"
...
10:24:28,415 DEBUG [org.jboss.seam.init.Initialization] (MSC service thread 1-1) initializing Seam
10:24:28,415 DEBUG [org.jboss.seam.contexts.ServletLifecycle] (MSC service thread 1-1) >>> Begin initialization
10:24:28,431 INFO [org.jboss.seam.Component] (MSC service thread 1-1) Component: org.jboss.seam.core.init, scope: APPLICATION, type: JAVA_BEAN, class: org.jboss.seam.core.Init
10:24:28,434 DEBUG [org.jboss.seam.Component] (MSC service thread 1-1) org.jboss.seam.core.init.distributable=false
10:24:28,439 DEBUG [org.jboss.seam.Component] (MSC service thread 1-1) org.jboss.seam.core.init.jndiPattern=java:app/booking-ejb/#{ejbName}
10:24:28,439 DEBUG [org.jboss.seam.Component] (MSC service thread 1-1) org.jboss.seam.core.init.debug=true
...
10:24:28,737 DEBUG [org.jboss.seam.contexts.Contexts] (MSC service thread 1-1) starting up: org.jboss.seam.navigation.pages
10:24:28,738 DEBUG [org.jboss.seam.faces.ResourceLoader] (MSC service thread 1-1) XXX: facesContext Seam Blog Example
10:24:28,739 DEBUG [org.jboss.seam.navigation.Pages] (MSC service thread 1-1) reading pages.xml file: /WEB-INF/pages.xml
10:24:28,743 DEBUG [org.jboss.seam.faces.ResourceLoader] (MSC service thread 1-1) XXX: facesContext Seam Blog Example
10:24:28,744 DEBUG [org.jboss.seam.util.Resources] (MSC service thread 1-1) Loaded resource from Seam classloader: blacklist.properties
10:24:28,748 DEBUG [org.jboss.seam.contexts.Contexts] (MSC service thread 1-1) starting up: org.jboss.seam.el.referenceCache
10:24:28,764 DEBUG [org.jboss.seam.contexts.Contexts] (MSC service thread 1-1) starting up: org.jboss.seam.security.entityPermissionChecker
10:24:28,764 DEBUG [org.jboss.seam.contexts.Contexts] (MSC service thread 1-1) starting up: org.jboss.seam.transaction.facesTransactionEvents
10:24:28,764 DEBUG [org.jboss.seam.contexts.Contexts] (MSC service thread 1-1) starting up: org.jboss.seam.security.facesSecurityEvents
10:24:28,765 DEBUG [org.jboss.seam.contexts.Contexts] (MSC service thread 1-1) destroying: warRootDeploymentStrategy
10:24:28,765 DEBUG [org.jboss.seam.contexts.Contexts] (MSC service thread 1-1) destroying: deploymentStrategy
10:24:28,765 DEBUG [org.jboss.seam.contexts.Contexts] (MSC service thread 1-1) destroying: hotDeploymentStrategy
10:24:28,765 DEBUG [org.jboss.seam.contexts.Contexts] (MSC service thread 1-1) destroying: org.jboss.seam.core.events
10:24:28,765 DEBUG [org.jboss.seam.contexts.ServletLifecycle] (MSC service thread 1-1) <<< End initialization
10:24:28,765 DEBUG [org.jboss.seam.init.Initialization] (MSC service thread 1-1) done initializing Seam
10:24:28,768 INFO [javax.enterprise.resource.webcontainer.jsf.config] (MSC service thread 1-1) Initializing Mojarra 2.1.7-jbossorg-2 (20120412-0335) for context '/seam-booking'
10:24:29,761 INFO [org.richfaces.log.Cache] (MSC service thread 1-1) Selected fallback cache factory
10:24:29,763 INFO [org.richfaces.log.Cache] (MSC service thread 1-1) Creating LRUMap cache instance using parameters: {org.richfaces.enableControlSkinning=false, javax.faces.DEFAULT_SUFFIX=.xhtml}
10:24:29,769 INFO [org.richfaces.log.Cache] (MSC service thread 1-1) Creating LRUMap cache instance of 512 items capacity
10:24:29,776 INFO [org.richfaces.log.Application] (MSC service thread 1-1) RichFaces Core Implementation by JBoss by Red Hat, version v.4.2.2.Final
10:24:29,778 WARNING [org.richfaces.log.Application] (MSC service thread 1-1) JMS API was found on the classpath; if you want to enable RichFaces Push JMS integration, set context-param 'org.richfaces.push.jms.enabled' in web.xml
10:24:29,780 INFO [org.jboss.seam.servlet.SeamFilter] (MSC service thread 1-1) Initializing filter: org.jboss.seam.web.hotDeployFilter
10:24:29,780 INFO [org.jboss.seam.servlet.SeamFilter] (MSC service thread 1-1) Initializing filter: org.jboss.seam.web.redirectFilter
10:24:29,780 INFO [org.jboss.seam.servlet.SeamFilter] (MSC service thread 1-1) Initializing filter: org.jboss.seam.web.exceptionFilter
10:24:29,780 INFO [org.jboss.seam.servlet.SeamFilter] (MSC service thread 1-1) Initializing filter: org.jboss.seam.web.multipartFilter
10:24:29,781 INFO [org.jboss.seam.servlet.SeamFilter] (MSC service thread 1-1) Initializing filter: org.jboss.seam.web.identityFilter
10:24:29,781 INFO [org.jboss.seam.servlet.SeamFilter] (MSC service thread 1-1) Initializing filter: org.jboss.seam.web.loggingFilter
10:24:29,782 INFO [org.jboss.web] (MSC service thread 1-1) JBAS018210: Registering web context: /seam-booking
10:24:29,980 INFO [org.jboss.as.server] (management-handler-thread - 2) JBAS018559: Deployed "seam-booking.ear"
{noformat}
Steps to Reproduce: Removed: 1. Start the AS7/EAP6 with ./standalone.sh -Dorg.jboss.server.bootstrap.maxThreads=1 (which makes it easier to reproduce, as the issue occurs only when both the deployments are handled by the same MSC service thread) 2. deploy seam-blog.ear 3. deploy seam-booking.ear 4. notice the seam-blog doesn't work Added: 1. Start the AS7/EAP6 with ./standalone.sh -Dorg.jboss.server.bootstrap.maxThreads=1 (which makes it easier to reproduce, as the issue occurs only when both the deployments are handled by the same MSC service thread) 2. deploy seam-blog.ear 3. deploy seam-booking.ear 4. notice the seam-blog doesn't work the ears can be found in http://file.brq.redhat.com/~maschmid/JBPAPP-9197/ Steps to Reproduce: Removed: 1. Start the AS7/EAP6 with ./standalone.sh -Dorg.jboss.server.bootstrap.maxThreads=1 (which makes it easier to reproduce, as the issue occurs only when both the deployments are handled by the same MSC service thread) 2. deploy seam-blog.ear 3. deploy seam-booking.ear 4. notice the seam-blog doesn't work the ears can be found in http://file.brq.redhat.com/~maschmid/JBPAPP-9197/ Added: 1. Start the AS7/EAP6 with ./standalone.sh -Dorg.jboss.server.bootstrap.maxThreads=1 (which makes it easier to reproduce, as the issue occurs only when both the deployments are handled by the same MSC service thread) 2. deploy seam-blog.ear 3. deploy seam-booking.ear 4. notice the seam-booking doesn't work the ears can be found in http://file.brq.redhat.com/~maschmid/JBPAPP-9197/ Marek N, Can someone on the Seam team take a look at this? I think it's far more likely to be a Seam issue than a JSF issue. If it were a JSF issue you would see lots and lots of non-Seam users complaining. BTW, the apps referenced here are using Seam 2.3.0.CR1-SNAPSHOT. Stan Stan,
Marek Schmidt is from Seam QE so he is aware of the context.
I think what is weird is
{noformat}
javax.faces.context.FacesContext.getCurrentInstance();
{noformat}
which gives the totally wrong context from previous application deployment initialization. That is not isolated from parallel applicaiton deployment?
The same problem reproducible with no Seam at all:
1. start jboss with ./standalone.sh -Dorg.jboss.server.bootstrap.maxThreads=1
(to make it more likely the two deployments are handled by the same thread)
2. deploy jboss-as-helloworld-1.war
3. deploy jboss-as-helloworld-2.war immediately after
4. notice the log
{noformat}
16:27:27,153 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: JBoss EAP 6.0.0.GA (AS 7.1.2.Final-redhat-1) started in 3546ms - Started 135 of 215 services (79 services are passive or on-demand)
16:27:31,404 INFO [org.jboss.as.repository] (management-handler-thread - 2) JBAS014900: Content added at location /home/maschmid/testing/eap6/jboss-eap-6.0.0.CR1/jboss-eap-6.0/standalone/data/content/f7/0c332126d93e65fcd2def44f171cb249e3d54f/content
16:27:31,426 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) JBAS015876: Starting deployment of "jboss-as-helloworld-1.war"
16:27:31,754 INFO [org.jboss.weld.deployer] (MSC service thread 1-1) JBAS016002: Processing weld deployment jboss-as-helloworld-1.war
16:27:31,840 INFO [org.jboss.weld.deployer] (MSC service thread 1-1) JBAS016005: Starting Services for CDI deployment: jboss-as-helloworld-1.war
16:27:31,945 INFO [org.jboss.weld.Version] (MSC service thread 1-1) WELD-000900 1.1.8 (redhat)
16:27:32,028 INFO [org.jboss.as.osgi] (MSC service thread 1-1) JBAS011907: Register module: Module "deployment.jboss-as-helloworld-1.war:main" from Service Module Loader
16:27:32,088 INFO [org.jboss.weld.deployer] (MSC service thread 1-1) JBAS016008: Starting weld service for deployment jboss-as-helloworld-1.war
16:27:32,453 INFO [stdout] (MSC service thread 1-1)
16:27:32,499 INFO [javax.enterprise.resource.webcontainer.jsf.config] (MSC service thread 1-1) Initializing Mojarra 2.1.7-jbossorg-2 (20120412-0335) for context '/jboss-as-helloworld-1'
16:27:33,512 INFO [org.hibernate.validator.util.Version] (MSC service thread 1-1) Hibernate Validator 4.2.0.Final-redhat-1
16:27:33,795 INFO [org.jboss.web] (MSC service thread 1-1) JBAS018210: Registering web context: /jboss-as-helloworld-1
16:27:33,989 INFO [org.jboss.as.server] (management-handler-thread - 2) JBAS018559: Deployed "jboss-as-helloworld-1.war"
16:27:35,714 INFO [org.jboss.as.repository] (management-handler-thread - 4) JBAS014900: Content added at location /home/maschmid/testing/eap6/jboss-eap-6.0.0.CR1/jboss-eap-6.0/standalone/data/content/9b/873b9889dfa9fdbd7131114a0c3b34f5ffb2a3/content
16:27:35,719 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) JBAS015876: Starting deployment of "jboss-as-helloworld-2.war"
16:27:35,753 INFO [org.jboss.weld.deployer] (MSC service thread 1-1) JBAS016002: Processing weld deployment jboss-as-helloworld-2.war
16:27:35,768 INFO [org.jboss.weld.deployer] (MSC service thread 1-1) JBAS016005: Starting Services for CDI deployment: jboss-as-helloworld-2.war
16:27:35,775 INFO [org.jboss.as.osgi] (MSC service thread 1-1) JBAS011907: Register module: Module "deployment.jboss-as-helloworld-2.war:main" from Service Module Loader
16:27:35,779 INFO [org.jboss.weld.deployer] (MSC service thread 1-1) JBAS016008: Starting weld service for deployment jboss-as-helloworld-2.war
16:27:35,854 INFO [stdout] (MSC service thread 1-1) Context Name: Hello World Example 1
16:27:35,857 INFO [javax.enterprise.resource.webcontainer.jsf.config] (MSC service thread 1-1) Initializing Mojarra 2.1.7-jbossorg-2 (20120412-0335) for context '/jboss-as-helloworld-2'
16:27:35,904 INFO [org.jboss.web] (MSC service thread 1-1) JBAS018210: Registering web context: /jboss-as-helloworld-2
16:27:36,068 INFO [org.jboss.as.server] (management-handler-thread - 4) JBAS018559: Deployed "jboss-as-helloworld-2.war"
{noformat}
{code}
public class HelloListener implements ServletContextListener
{
@Override
public void contextDestroyed(ServletContextEvent arg0)
{
}
@Override
public void contextInitialized(ServletContextEvent arg0)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext != null) {
System.out.println("Context Name: " + facesContext.getExternalContext().getContextName());
}
else {
System.out.println("");
}
}
}
{code}
{code}
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Hello World Example 1</display-name>
<listener>
<listener-class>org.jboss.as.quickstarts.helloworld.HelloListener</listener-class>
</listener>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
</web-app>
{code}
(the other has display-name "Hello World Example 2")
Attachment: Added: jboss-as-helloworld-1.war Attachment: Added: jboss-as-helloworld-2.war Also note that redeploying jboss-as-helloworld-2.war fails with
{noformat}
{16:37:43,018 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/jboss-as-helloworld-2]] (MSC service thread 1-1) Exception sending context initialized event to listener instance of class org.jboss.as.quickstarts.helloworld.HelloListener: java.lang.NullPointerException
at com.sun.faces.config.InitFacesContext$ServletContextAdapter.getContextName(InitFacesContext.java:317) [jsf-impl-2.1.7-redhat-1.jar:2.1.7-redhat-1]
at org.jboss.as.quickstarts.helloworld.HelloListener.contextInitialized(HelloListener.java:22) [classes:]
at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:3392) [jbossweb-7.0.16.Final-redhat-1.jar:]
at org.apache.catalina.core.StandardContext.start(StandardContext.java:3850) [jbossweb-7.0.16.Final-redhat-1.jar:]
at org.jboss.as.web.deployment.WebDeploymentService.start(WebDeploymentService.java:90) [jboss-as-web-7.1.2.Final-redhat-1.jar:7.1.2.Final-redhat-1]
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [rt.jar:1.6.0_30]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [rt.jar:1.6.0_30]
at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_30
{noformat}
which is also very odd.
I'm not sure how much everyone knows about this, so I'll summarize. FacesContext.getCurrentInstance() gets the FacesContext from a ThreadLocal variable. The FacesServlet is responsible for calling the FacesContextFactory to create the instance. The constructor for FacesContextImpl calls FacesContext.setCurrentInstance(this). This sets the ThreadLocal. The FacesServlet is also responsible for calling FacesContext.release() in a finally block. release() will remove the ThreadLocal. Thus, the FacesContext and its assignment to a ThreadLocal should only survive a single request. The error described in this jira is one where the ThreadLocal is not cleaned up at the end of the request. So the next request gets a "dirty" FacesContext from the thread used to service an earlier request. The kind of error we are seeing typically occurs when a framework does something to change or intercept the above logic. Some possibilities are a custom FacesServlet, FacesContextFactory, or FacesContext implementation. If Seam is using any of those then that's where you would start looking for the bug. So given all that, I'll state again that it's unlikely to be a bug in the JSF implementation. The JSF version we are using has been released for awhile now and I haven't been able to find complaints about FacesContext "leakage" problems. This would be a fairly obvious bug. Stan, in my second example, there is no Seam and there is no request. The problem occurs in a servlet listener contextInitialized method, which is called before the FacesServlet is started. So the problem seems to be that the FacesContext.release didn't work properly in the first deployment, as the second deployment gets this dirty FacesContext instance. Let me emphasise once more, the problem is with the FacesContext instance in the "MSC service thread 1-1", not the request threads. I guess I was busy writing my incorrect analysis while you were trying to tell me that you reproduced without Seam. I'll take a closer look. I believe I've found the problem. Notice in the log how you get
16:27:32,453 INFO [stdout] (MSC service thread 1-1)
For your code, this means that FacesContext is null because you do System.out.println("");
The problem is that your HelloListener is being called before the JSF listener. As a workaround for now you can add this to the top of your web.xml
{noformat}
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
{noformat}
As long as that listener comes before your declared listener then JSF will be initialized before you try to call FacesContext.getCurrentInstance().
I'll see if there is something we can do to make sure that the JSF listener comes first.
Marek S, Can you re-attach the Seam apps you originally used to create this problem? We will eventually need those for testing. Stan Stan, you can find ears in the Steps to reproduce at http://file.brq.redhat.com/~maschmid/JBPAPP-9197/ BTW, in JSF 2.x, the proper way to do what you are trying to do is to register for the PostConstructApplicationEvent. This was created in JSF2 to specifically address this situation. http://docs.oracle.com/cd/E17802_01/j2ee/javaee/javaserverfaces/2.0/docs/api/javax/faces/event/PostConstructApplicationEvent.html If you know that you are using JSF 2.x then you should not rely on a ServletContextListener. I just realized something else. If you are using JSF 1.x then calling FacesContext.getCurrentInstance() is not allowed outside of a servlet request. So it looks like we probably have a bug in Seam after all. You are required to use PostConstructApplicationEvent. Link: Added: This issue relates to JBSEAM-4980 OK, I created issue (JBSEAM-4980) for that as we are using JSF2 solely in Seam 2.3.0. Anyway that is a side effect for this issue, right? Do you have a fix for the original cause? {quote}
I'll see if there is something we can do to make sure that the JSF listener comes first.
{quote}
Would that really be the proper fix? If I understand this correctly, that would overwrite the facesContext ThreadLocal instance by a correct one, which is mostly fine from the app point of view, but it doesn't change the fact that there is a facesContext instance left over from the previous deployment.
IMHO it is perfectly fine to have FacesContext.getCurrentInstance return null in a ServletContextListener if I configure the FacesServlet to be started later. This also seems to be the behaviour which Seam is used to. So I think the only fix that is necessary is to release the FacesContext in the MSC service thread after application initialization.
To summarize, there are two issues:
1. FacesContext is not released in the MSC service thread after application initialization.
2. FacesContext is not initialized first.
I believe only 1. is the real issue, 2. is not an issue, makes sense only as workaround for 1.
Updating to critical, as this issue gives applications access to files belonging to a different deployment that has been handled by the same MSC service thread through the FacesContext.getCurrentInstance().getResourceAsStream(). Labels: Added: eap6_need_triage {quote}Anyway that is a side effect for this issue, right? Do you have a fix for the original cause?{quote}
Using a ServletContextListener to access FacesContext is the original cause. You shouldn't do that.
The issue here is that ordering of ServletContextListener is undefined. So you can not rely on FacesContext.getCurrentInstance() inside a ServletContextListener. Even if we set the order in AS it wouldn't be guaranteed to work on other containers.
{quote}
I'll see if there is something we can do to make sure that the JSF listener comes first.
Would that really be the proper fix?{quote}
No, that wouldn't be the proper fix. I never should have suggested it.
{quote}If I understand this correctly, that would overwrite the facesContext ThreadLocal instance by a correct one, which is mostly fine from the app point of view, but it doesn't change the fact that there is a facesContext instance left over from the previous deployment.{quote}
I think you have a good point here. It's fine as long as the app does things the right way. But Mojarra should not leave things in the ThreadLocal if it can help it. I'll open a Jira against Mojarra.
{quote}IMHO it is perfectly fine to have FacesContext.getCurrentInstance return null in a ServletContextListener if I configure the FacesServlet to be started later. This also seems to be the behaviour which Seam is used to. So I think the only fix that is necessary is to release the FacesContext in the MSC service thread after application initialization. {quote}
The problem is it's not fine to call FacesContext.getCurrentInstance() in a ServletContextListener. The spec should make this explicit, but it doesn't.
The ServletContextListener.contextInitialized() method will always be called before the FacesServlet is started, so I'm not sure what you mean by "if I configure the FacesServlet to be started later". If you can do what you need to do later, why would you code something to try at two different times?
{quote}
To summarize, there are two issues:
1. FacesContext is not released in the MSC service thread after application initialization.
2. FacesContext is not initialized first.
I believe only 1. is the real issue, 2. is not an issue, makes sense only as workaround for 1.
{quote}
Neither of those is an issue as far as Seam is concerned. If Seam does things according to the JSF spec then it will be OK.
{quote}
Updating to critical,{quote}
Unless I find out I'm wrong, I'll be closing this as "Wont Fix". See below. The JSF impl doesn't actually do anything wrong, though perhaps it could clean up a little better.
{quote}as this issue gives applications access to files belonging to a different deployment that has been handled by the same MSC service thread through the FacesContext.getCurrentInstance().getResourceAsStream().{quote}
I assume you mean FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream()? It is a violation of the JSF spec to call that during application initialization. (Well, technically, the call is undefined).
See http://docs.oracle.com/cd/E17802_01/j2ee/javaee/javaserverfaces/2.0/docs/api/javax/faces/context/ExternalContext.html
getResourceAsStream() does not have the "valid to call during startup" designation.
Yes, I meant FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream(), sorry
{quote}
getResourceAsStream() does not have the "valid to call during startup" designation.
{quote}
Yes it does. Unless I am reading it wrong, the docs you linked to says:
{quote}
It is valid to call this method during application startup or shutdown. If called during application startup or shutdown, this method calls through to the getResourceAsStream() method on the same container context instance (ServletContext or PortletContext) as the one used when calling getResourceAsStream() on the ExternalContext returned by the FacesContext during an actual request.
{quote}
And even if it would be undefined, I'd consider a behaviour which would allow you to retrieve resources from another deployment as a serious issue.
You're right. I didn't click through to the detail that says it is "valid to call". So it does indeed have that designation. However, that doesn't change the fact that you need to call it after notification from the PostConstructApplicationEvent. You can't rely on it from a ServletContextListener. I think you are also right that it's a serious issue for Mojarra because it could be a security concern and I'll note that in the jira for Mojarra. But as far as Seam is concerned, it still has to fix its code to stop using ServletContextListener to get FacesContext. I've opened this against Mojarra: http://java.net/jira/browse/JAVASERVERFACES-2436 Perhaps we should keep this open until the Mojarra team decides what they want to do. {quote}Perhaps we should keep this open until the Mojarra team decides what they want to do.{quote}
Looks like we got our answer. See Roger's comment on http://java.net/jira/browse/JAVASERVERFACES-2436.
Marek, you've uncovered a fine nest of bugs. So far we have:
2 JSF spec issues
1 Mojarra implementation issue
1 Seam implementation issue
Nice work.
Workaround Description: Added: Make sure that you do not try to call FacesContext.getCurrentInstance() from a ServletContextListener. If you are using FacesContext at application initialization it should only be done in response to a JSF PostConstructApplicationEvent. And then, you should always call FacesContext.release() in a finally block when you are done. Presumably, once http://java.net/jira/browse/JAVASERVERFACES-2436 is fixed, the call to FacesContext.release() will be done for you just as it is during a request to the FacesServlet. Lowering priority to major as this is not an EAP 6 GA blocker. Labels: Removed: eap6_need_triage Added: eap601candidate Mojarra has fixed this in 2.1.11. I've done a pull request to get our fork of that into EAP. Git Pull Request: Added: https://github.com/jbossas/jboss-as/pull/2731 This is now fixed in the latest EAP branch. Git Pull Request: Removed: https://github.com/jbossas/jboss-as/pull/2731 Added: https://github.com/jbossas/jboss-as/pull/2731 Git Pull Request: Removed: https://github.com/jbossas/jboss-as/pull/2731 Added: https://github.com/jbossas/jboss-as/pull/2731 Verified on EAP 6.0.1.ER2 Release Notes Docs Status: Added: Not Yet Documented Git Pull Request: Removed: https://github.com/jbossas/jboss-as/pull/2731 Added: https://github.com/jbossas/jboss-as/pull/2731 Affects: Added: Release Notes Updated release note fields. reopening for release notes updates Writer: Added: elogue Writer: Removed: elogue Added: tomwells Could someone please summarize the fix and result of this JIRA for the release notes, and check the Cause/Consequence below: Cause: FacesContext.getCurrentInstance sometimes returns a non-null instance belonging to a previous deployment. Consequence: When deploying two Seam2 applications, the second would occasionally not work, as configuration files were loaded from the first application. Thanks. Release Notes Docs Status: Removed: Not Yet Documented Added: Needs More Info It is a Mojarra issue, see the upstream summary of the changes http://java.net/jira/secure/attachment/50553/changebundle-2436.txt (from the upstream Mojarra issue http://java.net/jira/browse/JAVASERVERFACES-2436 ) To summarise the summary: The FacesContext that is made available during application startup (InitFacesContext) is held in a ThreadLocal. The reference was not properly cleaned up. The fix adds additional tracking and cleaning of the InitFacesContext references so that another deployment reusing the same thread won't get the InitFacesContext reference belonging to the previous deployment. The Cause and Consequence are mostly fine by me. The issue is not strictly Seam-specific, though. Any application that call FacesContext.getCurrentInstance() from a ServletContextListener would be affected and the resulting FacesContext instance might belong to a previous deployment (so the consequence depend on what exactly the application does with the FacesContext during startup, Seam uses it for reading configuration files, hence the Seam-specific consequence) Thanks Marek! Release Notes Docs Status: Removed: Needs More Info Added: Documented as Resolved Issue Release Notes Text: Added: In some situations, the <code>FaceContext.getCurrentInstance()</code> method call from a <classname>ServletContextListener</classname> during application startup returned the external context from a different deployment. This was caused by a failure to properly clean up the <classname>FacesContext</classname> that was held in a ThreadLocal, allowing a JSF WAR to gain access to another WAR's resources. The fix adds additional tracking and cleaning of the <classname>InitFacesContext<classname> references so that another deployment reusing the same thread won't get references belonging to the previous deployment. Git Pull Request: Removed: https://github.com/jbossas/jboss-as/pull/2731 Added: https://github.com/jbossas/jboss-as/pull/2731 Tom, I made a first pass at the release notes text. Feel free to edit as you see fit. Release Notes Text: Removed: In some situations, the <code>FaceContext.getCurrentInstance()</code> method call from a <classname>ServletContextListener</classname> during application startup returned the external context from a different deployment. This was caused by a failure to properly clean up the <classname>FacesContext</classname> that was held in a ThreadLocal, allowing a JSF WAR to gain access to another WAR's resources. The fix adds additional tracking and cleaning of the <classname>InitFacesContext<classname> references so that another deployment reusing the same thread won't get references belonging to the previous deployment. Added: In some situations, the <code>FaceContext.getCurrentInstance()</code> method call from a <classname>ServletContextListener</classname> during application startup returned the external context from a different deployment. This was caused by a failure to properly clean up the <classname>FacesContext</classname> that was held in a ThreadLocal, allowing a JSF WAR to gain access to another WAR's resources. Additional tracking and cleaning of the <classname>InitFacesContext<classname> references has been added, so that another deployment reusing the same thread won't get references belonging to the previous deployment. Release Notes Text: Removed: In some situations, the <code>FaceContext.getCurrentInstance()</code> method call from a <classname>ServletContextListener</classname> during application startup returned the external context from a different deployment. This was caused by a failure to properly clean up the <classname>FacesContext</classname> that was held in a ThreadLocal, allowing a JSF WAR to gain access to another WAR's resources. Additional tracking and cleaning of the <classname>InitFacesContext<classname> references has been added, so that another deployment reusing the same thread won't get references belonging to the previous deployment. Added: In some situations, the `FaceContext.getCurrentInstance()` method call from a `ServletContextListener` during application startup returned the external context from a different deployment. This was caused by a failure to properly clean up the `FacesContext` that was held in a ThreadLocal, allowing a JSF WAR to gain access to another WAR's resources. Additional tracking and cleaning of the `InitFacesContext` references has been added, so that another deployment reusing the same thread won't get references belonging to the previous deployment. Release Notes Docs Status: Removed: Documented as Resolved Issue Writer: Removed: tomwells Release Notes Text: Removed: In some situations, the `FaceContext.getCurrentInstance()` method call from a `ServletContextListener` during application startup returned the external context from a different deployment. This was caused by a failure to properly clean up the `FacesContext` that was held in a ThreadLocal, allowing a JSF WAR to gain access to another WAR's resources. Additional tracking and cleaning of the `InitFacesContext` references has been added, so that another deployment reusing the same thread won't get references belonging to the previous deployment. Docs QE Status: Removed: NEW closing, this has been verified on EAP 6.0.1.ER2 already. |