0

We are using dynamic binding components on our project.

Getting high CPU usage due to Multiple stuck threads at UIComponent.popComponentFromEL (UIComponent.java:2084) Every thread refers to the same line number in UIComponent.java at line 2084. Here is the snippet of thread dump.

javax.faces.component.UIComponent.popComponentFromEL(UIComponent.java:2084)
javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2326)
javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2314)
javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2314)
javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2314)
javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2314)
javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2314)
javax.faces.component.UIComponentBase.doPostAddProcessing(UIComponentBase.java:1986)
javax.faces.component.UIComponentBase.setParent(UIComponentBase.java:459)
javax.faces.component.UIComponentBase$ChildrenList.add(UIComponentBase.java:2772)
javax.faces.component.UIComponentBase$ChildrenList.add(UIComponentBase.java:2742)
com.sun.faces.facelets.tag.jsf.ComponentSupport.addComponent(ComponentSupport.java:527)
com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.addComponentToView(ComponentTagHandlerDelegateImpl.java:354)
com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.addComponentToView(ComponentTagHandlerDelegateImpl.java:337)
com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:222)
javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:135)
javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:96)
com.sun.faces.facelets.tag.jsf.core.ViewHandler.apply(ViewHandler.java:224)
javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:96)
com.sun.faces.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:94)
com.sun.faces.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:88)
com.sun.faces.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:313)
com.sun.faces.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:372)
com.sun.faces.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:351)
com.sun.faces.facelets.impl.DefaultFaceletContext.includeFacelet(DefaultFaceletContext.java:204)
com.sun.faces.facelets.tag.ui.CompositionHandler.apply(CompositionHandler.java:175)
com.sun.faces.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:94)
com.sun.faces.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:88)
com.sun.faces.facelets.impl.DefaultFacelet.apply(DefaultFacelet.java:162)
com.sun.faces.application.view.FaceletViewHandlingStrategy.buildView(FaceletViewHandlingStrategy.java:381)
com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:289)
com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:157)
com.ocpsoft.pretty.faces.application.PrettyViewHandler.restoreView(PrettyViewHandler.java:109)
com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:204)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:133)
com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:201)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:670)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:145)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:470)
org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:395)
org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:316)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:137)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:748)

I tried the solution provided in below answer but there are many pages in which we have implemented component binding and it is not possible to change the scope of every page. Stuck thread at UIComponent.popComponentFromEL I removed below code from UIComponent.java file and it seems to be working. Here is the full code file

for (UIComponent topComponent = componentELStack.peek();
     topComponent != this;
     topComponent = componentELStack.peek())
{
   topComponent.popComponentFromEL(context);
}

Can someone elaborate what is the purpose of topComponent.popComponentFromEL(context); What is the side effect of that, If I comment that code?

As per JSF form/GitHub issue tracker suggestion, I also add SERIALIZE_SERVER_STATE parameter in web.xml but no luck.

<context-param>
    <param-name>javax.faces.SERIALIZE_SERVER_STATE</param-name>
    <param-value>true</param-value>
</context-param>

Also, try to change JSF version 2.2 still issue is persists

Environment :

  1. Mojarra JSF 2.3.2
  2. Java 8
  3. Primefaces 6.1
  4. Tomcat 8.5
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Divyesh Kanzariya
  • 3,629
  • 3
  • 43
  • 44
  • 1
    Can you add you explicit Mojarra version? 'JSF 2.3' is just an api version – Kukeltje Nov 12 '19 at 06:57
  • the explicit version is JSF 2.3.2 @Kukeltje – Divyesh Kanzariya Nov 12 '19 at 07:14
  • Mojarra, MyFaces or other implementation of JSF 2.3.2 API? – Selaron Nov 12 '19 at 07:44
  • we are using Mojarra implementation @Selaron – Divyesh Kanzariya Nov 12 '19 at 07:46
  • @BalusC any comment on this? – Divyesh Kanzariya Nov 12 '19 at 09:12
  • 1
    @Selaron: Mojarra could already be deducted from the stacktrace... Divyesh: I would expect BalusC (requesting help is not 'appreciated' btw) to not state explicitly whether removal of this code is good or bad. The code is there for a reason, so removal might in situations result in other unclear problems. I would expect him to say what is already stated in the other Q/A to correct the problem: _"Fix the code accordingly that this never happens. Components are inherently request scoped and may absolutely not be shared across multiple requests."_ – Kukeltje Nov 12 '19 at 09:16
  • @Kukeltje oups :0 – Selaron Nov 12 '19 at 10:36

1 Answers1

3

I removed below code from UIComponent.java file and it seems to be working. Here is the code snippet:

for (UIComponent topComponent = componentELStack.peek();
     topComponent != this;
     topComponent = componentELStack.peek())
{
   topComponent.popComponentFromEL(context);
}

Can someone elaborate what is the purpose of topComponent.popComponentFromEL(context); What is the side effect of that, if I remove that code?

This piece of code basically manages the implicit EL expression #{component} in JSF pages. Removing it will affect the behavior of #{component} in EL. For example, in the following construct,

<h:someComponent id="foo">
    <h:someComponent id="bar" />
    #{component}
</h:someComponent>

... the expected behavior is that #{component} will give you the one with id="foo". But with your change, it will incorrectly give you the one with id="bar".


As per JSF form/GitHub issue tracker suggestion, I also add SERIALIZE_SERVER_STATE parameter in web.xml but no luck.

<context-param>
    <param-name>javax.faces.SERIALIZE_SERVER_STATE</param-name>
    <param-value>true</param-value>
</context-param>

This won't work when you assign component bindings to a transient property. Even when you fix that, this still won't really "solve" your problem. It will just throw a NotSerializableException at a much sooner moment. Already when you just open the JSF page, instead of that you're facing a "Stuck thread" error when multiple users open the JSF page. The NotSerializableException should give a clear warning to the developer that the developer is doing something completely wrong.


Also, try to change JSF version 2.2 still issue is persists

The problem you faced is not a JSF version specific problem. It's a developer mistake. Just never assign UIComponent as a property of a managed bean which is in a broader scope than @RequestScoped. See also How does the 'binding' attribute work in JSF? When and how should it be used?

Just do not fix the problem by removing the piece of code from UIComponent.java. You will still have a non-threadsafe JSF webapplication. When user X modifies one property of a particular component, e.g. disabled becomes true, then it will affect all other users as well, and this will end up in a non-working webapp.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks for detailed expiation as we observe `for loop` recursive call and not the break. https://github.com/eclipse-ee4j/mojarra/issues/3827#issuecomment-382248850 what is your view on this fix? – Divyesh Kanzariya Nov 14 '19 at 11:38
  • 1
    I disagree that. It's basically hiding a major underlying problem: a non-threadsafe webapp. You should not attempt to fix that by covering/suppressing/hiding all possible exceptions it could cause, no. You should attempt to fix that by its very root problem: just never bind components to a bean which is not in request scope. Then all its possible consequences/exceptions will simply solve by themselves and you end up with a threadsafe webapp. That's what you and your company ultimately want, right? – BalusC Nov 14 '19 at 11:40
  • there is an alternative of component binding when we use view scope? because when we use request scope there is lots of code refactoring needed. – Divyesh Kanzariya Nov 14 '19 at 11:45
  • 1
    Yes. I have explained all alternatives in the "See also" link mentioned in my answer. You do absolutely not need to migrate the scope of all your beans. You only need to migrate all your `binding` usage. More than often, it's not needed at all. – BalusC Nov 14 '19 at 11:45
  • thanks for your view on this. I will be looking at your solution. – Divyesh Kanzariya Nov 14 '19 at 11:53
  • In long run, I think your approach is correct to do the binding and scope related changes. When I tried the patch to break the infinite calls, I didn't see any issue in the application. Can you just suggest me steps to be followed to replicate the problem which you are referring to? – Divyesh Kanzariya Nov 15 '19 at 14:47
  • If you're not using `#{component}` anywhere then there's no problem when applying this "patch". But your application is still not threadsafe after applying this "patch". You still need to fix the problem by its root. If you can tell in detail why and how exactly you're using `binding`, then it's for me easier to point out a more specific answer how to correctly replace it. – BalusC Nov 15 '19 at 14:52
  • sorry for let replay here is the code snippet https://gist.github.com/geekdiv/229101db5af47f42f3310e16711f0498 – Divyesh Kanzariya Nov 21 '19 at 10:32
  • Ahhh .. Just replacing Java by XHTML is the best solution there. – BalusC Nov 21 '19 at 10:46
  • we have a dynamic form builder how we can achieve it via xhtml? – Divyesh Kanzariya Nov 21 '19 at 10:49
  • Woah, that's a broad question. It's is much easier to answer if you break down your problem in chunks and tell in detail at which step exactly you're stucking. E.g. "How do I loop over a collection in XHTML?" which can be answered as "Use `` or ``". Then we can advance to next step/question. You can always find more elaborate code examples in the link in my answer (and in the links thereof). – BalusC Nov 21 '19 at 11:53