ICEfaces
  1. ICEfaces
  2. ICE-1365

Threads used by RenderManager have incorrect context classloader.

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 1.5.3, 1.6DR#2
    • Fix Version/s: 1.6DR#3, 1.6
    • Component/s: Framework
    • Labels:
      None
    • Environment:
      All current versions of ICEfaces and various application servers.

      Description

      The RenderManager uses it's own thread pool to execute server-side render calls for AJAX-push events. Since thread creation in application servers is not clear in the Servlet spec (it's not forbidden but also not encouraged), servlet container implementations vary on how they deal with user-created threads. We originally had a problem with WebSphere where the created threads did not have the appropriate context classloader set and would then have problems finding the appropriate JSF factories to complete the render call.

      To alleviate the problem with WebSphere, we forced a context classloader to be set on all the new threads we created via our own RenderThreadFactory. Unfortunately this solution is too blunt and makes incorrect assumptions about which classloader is appropriate for the new threads. The combination of deployment method (war vs ear) and app server can cause additional classloader issues. We are currently looking at a slightly more sophisticated way of handling the classloader issue so that it works for all app servers that we support and with all methods of application deployment (i.e. war and ear).

        Activity

        Hide
        Ken Fyten added a comment -

        As this issue essentially prevents the use of the RenderManager in EAR deployments it should be fixed ASAP.

        Show
        Ken Fyten added a comment - As this issue essentially prevents the use of the RenderManager in EAR deployments it should be fixed ASAP.
        Hide
        Maxime Turner added a comment -

        Here's an EAR running on jBoss 4.0.5 GA that can reproduce the problem.

        (I don't know if i should've post in the forum instead)

        it consist of a War and ejb-jar inside an EAR
        From the TestPush/index.faces page you are able to click on a button to send a JMS message to a topic.

        The message is then received from a MessageDrivenBean that delivers it to the BackingBean, in the backing bean a requestRender() is called. That's when the problem occurs.

        I've included the TestPush sources if needed.

        Thank you.

        Show
        Maxime Turner added a comment - Here's an EAR running on jBoss 4.0.5 GA that can reproduce the problem. (I don't know if i should've post in the forum instead) it consist of a War and ejb-jar inside an EAR From the TestPush/index.faces page you are able to click on a button to send a JMS message to a topic. The message is then received from a MessageDrivenBean that delivers it to the BackingBean, in the backing bean a requestRender() is called. That's when the problem occurs. I've included the TestPush sources if needed. Thank you.
        Hide
        Deryk Sinotte added a comment -

        I was able to replicate the issue and then modified the test case to run across several different app servers. Surprising how much work is involved in setting up a simple EAR to run on various containers.

        The problem is definitely related to classloading. If the context classloader of the thread that originates the server-side render request comes from outside the web application context (e.g. a JMS message, Web Service, etc), then it cannot find the valid and appropriate JSF artifacts that it needs to run the JSF lifecyle events - execute() and render().

        One way to reliably get the correct classloader is for the PersistentFacesState to keep a reference to the context classloader of the thread that called its constructor. New threads created in the RenderManager's pool are then given a reference to this classloader as their own context classloader before the lifecycle methods are executed. That way, the rendering thread has access to the proper web application context. The original code was not setting a context classloader that was reliably in the proper context.

        The change has been committed to both the 1.5 branch and the 1.6 trunk (revision 13460).

        Show
        Deryk Sinotte added a comment - I was able to replicate the issue and then modified the test case to run across several different app servers. Surprising how much work is involved in setting up a simple EAR to run on various containers. The problem is definitely related to classloading. If the context classloader of the thread that originates the server-side render request comes from outside the web application context (e.g. a JMS message, Web Service, etc), then it cannot find the valid and appropriate JSF artifacts that it needs to run the JSF lifecyle events - execute() and render(). One way to reliably get the correct classloader is for the PersistentFacesState to keep a reference to the context classloader of the thread that called its constructor. New threads created in the RenderManager's pool are then given a reference to this classloader as their own context classloader before the lifecycle methods are executed. That way, the rendering thread has access to the proper web application context. The original code was not setting a context classloader that was reliably in the proper context. The change has been committed to both the 1.5 branch and the 1.6 trunk (revision 13460).
        Hide
        Deryk Sinotte added a comment -

        Resolving as Fixed for 1.6 DR #3 and 1.5.4.

        Show
        Deryk Sinotte added a comment - Resolving as Fixed for 1.6 DR #3 and 1.5.4.

          People

          • Assignee:
            Unassigned
            Reporter:
            Deryk Sinotte
          • Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: