ICEfaces
  1. ICEfaces
  2. ICE-6617

Issues with ICEFaces 1.8.x Spring Webflow, and WebSphere AS

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.8.2-EE-GA_P02
    • Fix Version/s: EE-1.8.2.GA_P03
    • Component/s: Framework
    • Labels:
      None
    • Environment:
      ICEFaces 1.8 P02, Spring webflow 1.0.5, WebSphere AS

      Description

      There are a couple of Spring Webflow related issues reported. This case details ongoing efforts in both.

      What we have is an application that wont start in Websphere. Trying to load the initial page shows the following error in the log:

      Caused by: java.lang.IllegalStateException: SRVE0199E: OutputStream already obtained
          at com.ibm.ws.webcontainer.srt.SRTServletResponse.getWriter(SRTServletResponse.java:591)
      at com.sun.facelets.FaceletViewHandler.createResponseWriter(FaceletViewHandler.java:414)
          at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:571)
          at com.icesoft.faces.application.D2DViewHandler.renderView(D2DViewHandler.java:150)
          at org.springframework.faces.webflow.JsfView.render(JsfView.java:97)
          at org.springframework.webflow.engine.ViewState.render(ViewState.java:253)
          at org.springframework.webflow.engine.ViewState.resume(ViewState.java:208)
          at org.springframework.webflow.engine.Flow.resume(Flow.java:545)
          at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:259)


        Activity

        Hide
        Greg Dick added a comment -

        It turns out that WebSphere isn't properly honoring the Servlet load-on-startup setting. The side effect of this is that the SpringWebflowInstantiationServlet (hereafter: SWfIS) isn't being loaded prior to the PersistentFacesServlet, and the SeamUtilities class that is attempting to determine if Spring is present is failing. I'm not sure what the actual result of this is, there are a few places where decisions are made using the Spring flag, but it's safe to say this application wont work if this flag is wrong.

        It's apparent that the code in SeamUtilities is misplaced, and that the detection of whether Spring is present belongs in the SWfIS. In WebSphere it is eventually loaded, and it could set a flag in SeamUtilities (in order to minimize the API disruption the isSpringEnvironment method should remain in SeamUtilities) when it is loaded.

        For the purpose of this customer, it's simple enough to remove part of the test on line 504 of SeamUtilities:

        try

        { springClass = Class.forName(SPRING_CONTEXT_HOLDER); }

        catch (Throwable t) {
        if (log.isDebugEnabled())

        { log.debug("Spring webflow 2.x not detected: " + t); }

        }
        if (null != springClass && springWebFlowConfigured() ) { <---------------------- Line 504
        springLoaded = 2;
        if (log.isDebugEnabled())

        { log.debug("Spring webflow detected: " + springClass); }

        }

        To this:

        if (null != springClass ) { <---------------------- Line 504
        springLoaded = 2;

        That allows the Spring detection code to work as required.

        Show
        Greg Dick added a comment - It turns out that WebSphere isn't properly honoring the Servlet load-on-startup setting. The side effect of this is that the SpringWebflowInstantiationServlet (hereafter: SWfIS) isn't being loaded prior to the PersistentFacesServlet, and the SeamUtilities class that is attempting to determine if Spring is present is failing. I'm not sure what the actual result of this is, there are a few places where decisions are made using the Spring flag, but it's safe to say this application wont work if this flag is wrong. It's apparent that the code in SeamUtilities is misplaced, and that the detection of whether Spring is present belongs in the SWfIS. In WebSphere it is eventually loaded, and it could set a flag in SeamUtilities (in order to minimize the API disruption the isSpringEnvironment method should remain in SeamUtilities) when it is loaded. For the purpose of this customer, it's simple enough to remove part of the test on line 504 of SeamUtilities: try { springClass = Class.forName(SPRING_CONTEXT_HOLDER); } catch (Throwable t) { if (log.isDebugEnabled()) { log.debug("Spring webflow 2.x not detected: " + t); } } if (null != springClass && springWebFlowConfigured() ) { <---------------------- Line 504 springLoaded = 2; if (log.isDebugEnabled()) { log.debug("Spring webflow detected: " + springClass); } } To this: if (null != springClass ) { <---------------------- Line 504 springLoaded = 2; That allows the Spring detection code to work as required.
        Hide
        Greg Dick added a comment -

        A follow up issue had the icefaces buttons not working. It looked like the external context wasn't keeping track of the fact that redirection had been requested, but the customer has reported that another Class loading issue is preventing a isJSF12 flag from being set. This flag changes the way the request maps are handled and would affect whether ICEFaces detects a request as a Spring request.

        It's not clear why this Class isn't available for class loading at startup.

        To temporarily get them working, the following lines of code may be used to hardcode JSF1.2 detection. They would replace lines 114 -> 151 in com.icesoft.faces.webapp.parser.ImplementationUtil.java. I've added a few lines of system outs for the code, there is java logging in place but sometimes getting output can be troublesome in WebSphere.

        //Test for JSF 1.2 <-- line 114
        try

        { Class.forName(JSF12_MARKER); isJSF12 = true; }

        catch (Throwable t)

        { System.out.println("___--- JSF12 NOT Detected __"); }

        System.out.println("__ Setting JSF12 to true for patch __");
        isJSF12 = true;

        if (log.isTraceEnabled())

        { log.trace("JSF-12: " + isJSF12); }

        //Test for JSF 2
        try

        { Class.forName(JSF2_MARKER); isJSF2 = true; }

        catch (Throwable t)

        { System.out.println("__--- JSF2.0 NOT Detected (that's good)_"); }

        if (log.isTraceEnabled())

        { log.trace("JSF-2: " + isJSF2); }

        try

        { Class.forName(MYFACES_MARKER); isMyFaces = true; //Disable JSF12 detection in MyFaces environment isJSF12 = false; System.out.println("__ MYFACES Detected _____--- DISABLING JSF12 _"); }

        catch (ClassNotFoundException e) {
        }

        if (log.isTraceEnabled())

        { log.trace("JSF-RI: " + isRI + " MyFaces: " + isMyFaces); }

        // < - line 151

        Show
        Greg Dick added a comment - A follow up issue had the icefaces buttons not working. It looked like the external context wasn't keeping track of the fact that redirection had been requested, but the customer has reported that another Class loading issue is preventing a isJSF12 flag from being set. This flag changes the way the request maps are handled and would affect whether ICEFaces detects a request as a Spring request. It's not clear why this Class isn't available for class loading at startup. To temporarily get them working, the following lines of code may be used to hardcode JSF1.2 detection. They would replace lines 114 -> 151 in com.icesoft.faces.webapp.parser.ImplementationUtil.java. I've added a few lines of system outs for the code, there is java logging in place but sometimes getting output can be troublesome in WebSphere. //Test for JSF 1.2 <-- line 114 try { Class.forName(JSF12_MARKER); isJSF12 = true; } catch (Throwable t) { System.out.println("___--- JSF12 NOT Detected __"); } System.out.println("__ Setting JSF12 to true for patch __"); isJSF12 = true; if (log.isTraceEnabled()) { log.trace("JSF-12: " + isJSF12); } //Test for JSF 2 try { Class.forName(JSF2_MARKER); isJSF2 = true; } catch (Throwable t) { System.out.println("__--- JSF2.0 NOT Detected (that's good)_"); } if (log.isTraceEnabled()) { log.trace("JSF-2: " + isJSF2); } try { Class.forName(MYFACES_MARKER); isMyFaces = true; //Disable JSF12 detection in MyFaces environment isJSF12 = false; System.out.println("__ MYFACES Detected _____--- DISABLING JSF12 _"); } catch (ClassNotFoundException e) { } if (log.isTraceEnabled()) { log.trace("JSF-RI: " + isRI + " MyFaces: " + isMyFaces); } // < - line 151
        Hide
        Greg Dick added a comment -

        i've checked in a general purpose change for the code, allowing a context param

        com.icesoft.faces.forceJSF12

        To be defined with a boolean parameter that overrides the classloading detection. Oddly, in my test, the value of this flag could not be read (despite being readable in the auctionMonitor application), so if this is important, the following logging conditions exist:

        try {
        String value = ec.getInitParameter(FORCE_JSF12);
        if (value != null && !"".equals(value))

        { isJSF12 = Boolean.parseBoolean( value ); log.debug("JSF12 force parameter detected: " + isJSF12); ImplementationUtil.setJSF12( isJSF12 ); }

        else

        { log.debug("JSF12 force parameter not detected: " + value); }

        } catch

        If this block isn't working, turn on debug level logging in WebSphere and check to see that the parameter is read correctly. It may be that the parameter isn't read if I just change web.xml in the exploded installed directory of websphere.

        I'm almost positive there will be other shoes to fall on this one. This type of classloading behaviour can't be good.

        Show
        Greg Dick added a comment - i've checked in a general purpose change for the code, allowing a context param com.icesoft.faces.forceJSF12 To be defined with a boolean parameter that overrides the classloading detection. Oddly, in my test, the value of this flag could not be read (despite being readable in the auctionMonitor application), so if this is important, the following logging conditions exist: try { String value = ec.getInitParameter(FORCE_JSF12); if (value != null && !"".equals(value)) { isJSF12 = Boolean.parseBoolean( value ); log.debug("JSF12 force parameter detected: " + isJSF12); ImplementationUtil.setJSF12( isJSF12 ); } else { log.debug("JSF12 force parameter not detected: " + value); } } catch If this block isn't working, turn on debug level logging in WebSphere and check to see that the parameter is read correctly. It may be that the parameter isn't read if I just change web.xml in the exploded installed directory of websphere. I'm almost positive there will be other shoes to fall on this one. This type of classloading behaviour can't be good.
        Hide
        Greg Dick added a comment -

        WebSphere does provide a ClassLoader Viewer tab in its management console. It appears (to my untrained eye) that all the jars in the WebApplication are on the WAS Module classpath. In the entire WebSphere installation directory, there is only one version of the javax.faces.webapp.UIComponentELTag class (in the correct place btw). That this code can't classload this class seems really odd to me at the moment.

        Show
        Greg Dick added a comment - WebSphere does provide a ClassLoader Viewer tab in its management console. It appears (to my untrained eye) that all the jars in the WebApplication are on the WAS Module classpath. In the entire WebSphere installation directory, there is only one version of the javax.faces.webapp.UIComponentELTag class (in the correct place btw). That this code can't classload this class seems really odd to me at the moment.
        Hide
        Greg Dick added a comment -

        I have changed the code in SeamUtilities so that instead of calling a getter on the SpringWebflowInstantiationServlet to fetch the flag, the SpringWebflowInstantiationServlet can now call a static setter on the SeamUtilities class. This prevents the order of operations error seen before. It's true that the SeamUtilities class is still loaded through a call chain from one of the other servlets, but I added a call to re-evaluate the Spring settings on startup and this works in WebSphere where we were having the problems.

        Show
        Greg Dick added a comment - I have changed the code in SeamUtilities so that instead of calling a getter on the SpringWebflowInstantiationServlet to fetch the flag, the SpringWebflowInstantiationServlet can now call a static setter on the SeamUtilities class. This prevents the order of operations error seen before. It's true that the SeamUtilities class is still loaded through a call chain from one of the other servlets, but I added a call to re-evaluate the Spring settings on startup and this works in WebSphere where we were having the problems.

          People

          • Assignee:
            Greg Dick
            Reporter:
            Greg Dick
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: