MyFaces Core
  1. MyFaces Core
  2. MYFACES-1955

MyFaces 1.2.4 and WebLogic 10.3- strict servlet API: cannot call getWriter() after getOutputStream()

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.2.2, 1.2.3, 1.2.4
    • Fix Version/s: 1.2.8
    • Component/s: None
    • Labels:
      None
    • Environment:
      Windows Vista, WebLogic 10.3, MyFaces 1.2.4

      Description

      I am trying to run a very simple JSF application using myFaces 1.2.4 and WebLogic 10.3. The application has the following content:
      web.xml:
      <?xml version="1.0" encoding="ISO-8859-1"?>
      <web-app 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_2_5.xsd"
      version="2.5">
      <servlet>
      <servlet-name>Faces Servlet</servlet-name>
      <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
      <servlet-name>Faces Servlet</servlet-name>
      <url-pattern>*.faces</url-pattern>
      </servlet-mapping>
      <welcome-file-list>
      <welcome-file>index.html</welcome-file>
      </welcome-file-list>
      </web-app>

      faces-config.xml:
      <?xml version="1.0"?>
      <faces-config 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-facesconfig_1_2.xsd"
      version="1.2">
      <navigation-rule>
      <from-view-id>/index.jsp</from-view-id>
      <navigation-case>
      <from-outcome>login</from-outcome>
      <to-view-id>/welcome.jsp</to-view-id>
      </navigation-case>
      </navigation-rule>
      <managed-bean>
      <managed-bean-name>user</managed-bean-name>
      <managed-bean-class>pt.pm.richfaces.UserBean</managed-bean-class>
      <managed-bean-scope>session</managed-bean-scope>
      </managed-bean>
      </faces-config>

      index.html:
      <html>
      <head>
      <meta http-equiv="Refresh" content= "0; URL=index.faces"/>
      <title>Start Web Application</title>
      </head>
      <body>
      <p>Please wait for the web application to start...</p>
      </body>
      </html>

      index.jsp:
      <html>
      <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
      <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
      <f:view>
      <head>
      <title>A Simple JavaServer Faces Application</title>
      </head>
      <body>
      <h:form>
      <h3>Please enter your name and password.</h3>
      <table>
      <tr>
      <td>Name:</td>
      <td><h:inputText value="#

      {user.name}" /></td>
      </tr>
      <tr>
      <td>Password:</td>
      <td><h:inputSecret value="#{user.password}" /></td>
      </tr>
      </table>
      <p><h:commandButton value="Login" action="login" /></p>
      </h:form>
      </body>
      </f:view>
      </html>

      My WEB_INF/lib contains the following jars: commons-beanutils-1.7.0, commons-codec-1.3, commons-collections-3.2, commons-digester-1.8, commons-discovery-0.4, commons-logging-1.1.1, glassfish.el_2.1.0, glassfish.jstl_1.2.0.1, myfaces-api-1.2.4, myfaces-impl-1.2.4.

      Whenever I try to run my application I get the following exception:

      java.lang.IllegalStateException: strict servlet API: cannot call getWriter() aft
      er getOutputStream()
      at weblogic.servlet.internal.ServletResponseImpl.getWriter(ServletRespon
      seImpl.java:308)
      at org.apache.myfaces.application.jsp.JspViewHandlerImpl.renderView(JspV
      iewHandlerImpl.java:362)
      at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderRes
      ponseExecutor.java:41)
      at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:
      140)
      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:155)

      If instead of using myFaces I use the Sun Reference implementation everything goes well. If I deploy the application (using myFaces) in JBoss 5 it works well. So the problem seems to be related with the use of WLS 10.3 and myFaces 1.2.4.

      I tried with 1.2.3 and 1.2.2 and got the issue with both. I tried with 1.2.0 and got another error:

      javax.faces.FacesException: weblogic.servlet.jsp.CompilationException: Failed to compile JSP /index.jsp
      index.jsp:14:22: Static attribute must be a String literal, its illegal to specify an expression.
      <td><h:inputText value="#{user.name}

      " /></td>

      1. MYFACES-1955.patch
        0.8 kB
        Leonardo Uribe

        Activity

        Hide
        Paulo Moreira added a comment -

        Same issue occurs with WebLogic 10 MP1.

        Show
        Paulo Moreira added a comment - Same issue occurs with WebLogic 10 MP1.
        Hide
        Vasil Svetoslavov added a comment -

        Also tested with MyFaces 1.2.6 on WebLogic 10.3 running on Windows XP

        Show
        Vasil Svetoslavov added a comment - Also tested with MyFaces 1.2.6 on WebLogic 10.3 running on Windows XP
        Hide
        Leonardo Uribe added a comment -

        The problem is related to a unwanted call to response.getOutputStream() from some part of myfaces core.

        The only call is on org.apache.myfaces.application.jsp.ViewResponseWrapper, method flushToWrappedResponse().

        The idea of this call is solve MYFACES-1815 (Resources under /faces/* returns empty). This solution is right but a side effect occur on org.apache.myfaces.taglib.core.ViewTag

        The related code is this:

        public int doStartTag() throws JspException
        {
        if (log.isTraceEnabled()) log.trace("entering ViewTag.doStartTag");

        FacesContext facesContext = FacesContext.getCurrentInstance();
        Object response = facesContext.getExternalContext().getResponse();
        if (response instanceof ViewResponseWrapper)
        {
        try

        { pageContext.getOut().flush(); ((ViewResponseWrapper) response).flushToWrappedResponse(); }

        catch (IOException e)

        { throw new JspException("Can't write content above <f:view> tag" + " " + e.getMessage()); }

        }

        The comment that says why this code exist is this:

        revision 494409: JspViewHandlerImpl now working an rendering output to the page. Created wrapper for the response, so the rendered code can be mixed with other code. Flushing when the view tag is started

        The default execution uses getOuputStream because there is no previous call to getWriter, which initialize a PrintWriter.

        The solution is do this:

        public int doStartTag() throws JspException
        {
        if (log.isTraceEnabled()) log.trace("entering ViewTag.doStartTag");

        FacesContext facesContext = FacesContext.getCurrentInstance();
        Object response = facesContext.getExternalContext().getResponse();
        if (response instanceof ViewResponseWrapper)
        {
        try

        { pageContext.getOut().flush(); ViewResponseWrapper wrapper = (ViewResponseWrapper) response; //Ensure usage CharArrayWriter calling response.getWriter(), //so flushToWrappedResponse does not call response.getOuputStream() wrapper.getWriter(); wrapper.flushToWrappedResponse(); }

        catch (IOException e)

        { throw new JspException("Can't write content above <f:view> tag" + " " + e.getMessage()); }

        }

        It could be good if anyone can probe this solution on WebLogic, so we can commit this solution.

        Show
        Leonardo Uribe added a comment - The problem is related to a unwanted call to response.getOutputStream() from some part of myfaces core. The only call is on org.apache.myfaces.application.jsp.ViewResponseWrapper, method flushToWrappedResponse(). The idea of this call is solve MYFACES-1815 (Resources under /faces/* returns empty). This solution is right but a side effect occur on org.apache.myfaces.taglib.core.ViewTag The related code is this: public int doStartTag() throws JspException { if (log.isTraceEnabled()) log.trace("entering ViewTag.doStartTag"); FacesContext facesContext = FacesContext.getCurrentInstance(); Object response = facesContext.getExternalContext().getResponse(); if (response instanceof ViewResponseWrapper) { try { pageContext.getOut().flush(); ((ViewResponseWrapper) response).flushToWrappedResponse(); } catch (IOException e) { throw new JspException("Can't write content above <f:view> tag" + " " + e.getMessage()); } } The comment that says why this code exist is this: revision 494409: JspViewHandlerImpl now working an rendering output to the page. Created wrapper for the response, so the rendered code can be mixed with other code. Flushing when the view tag is started The default execution uses getOuputStream because there is no previous call to getWriter, which initialize a PrintWriter. The solution is do this: public int doStartTag() throws JspException { if (log.isTraceEnabled()) log.trace("entering ViewTag.doStartTag"); FacesContext facesContext = FacesContext.getCurrentInstance(); Object response = facesContext.getExternalContext().getResponse(); if (response instanceof ViewResponseWrapper) { try { pageContext.getOut().flush(); ViewResponseWrapper wrapper = (ViewResponseWrapper) response; //Ensure usage CharArrayWriter calling response.getWriter(), //so flushToWrappedResponse does not call response.getOuputStream() wrapper.getWriter(); wrapper.flushToWrappedResponse(); } catch (IOException e) { throw new JspException("Can't write content above <f:view> tag" + " " + e.getMessage()); } } It could be good if anyone can probe this solution on WebLogic, so we can commit this solution.
        Hide
        Guillaume Menguy added a comment -

        I tried the solution above ( myfaces-core 1.2.6 patched with the MYFACES-1955.patch ) under Weblogic 10.3

        Unfortunately it does not work, an exception is now thrown by MyFaces itself :

        java.lang.IllegalStateException
        at org.apache.myfaces.application.jsp.ViewResponseWrapper.getWriter(ViewResponseWrapper.java:129)
        at org.apache.myfaces.taglib.core.ViewTag.doStartTag(ViewTag.java:100)
        at jsp_servlet.faces.face._jsptag0(_face.java:102)
        at jsp_servlet.faces.face._jspService(_face.java:75)
        at weblogic.servlet.jsp.JspBase.service(JspBase.java:34)

        Apparently, before the view tag calls the getWriter() on the instance of ViewResponseWrapper, the other method getOutputStream() has already been called twice before (I added a logger on it) by MyFaces implementation and, as I understand in the code of ViewResponseWrapper, the same instance cannot work with both a CharArrayWriter and a OutputStream instantiated inside.

        Maybe it can help, I added a dumpStack() in the method public ServletOutputStream getOutputStream() throws IOException

        {.. }

        of ViewResponseWrapper to understand which parts of MyFaces are calling it before the view tag does a getWriter()

        1st call:
        at java.lang.Thread.dumpStack(Thread.java:1206)
        at org.apache.myfaces.application.jsp.ViewResponseWrapper.getOutputStream(ViewResponseWrapper.java:116)
        at weblogic.servlet.internal.DelegateChunkWriter.write(DelegateChunkWriter.java:108)
        at weblogic.servlet.internal.ChunkOutputWrapper.write(ChunkOutputWrapper.java:139)
        at weblogic.servlet.jsp.JspWriterImpl.write(JspWriterImpl.java:274)
        at jsp_servlet.faces.face._jspService(_face.java:73)
        at weblogic.servlet.jsp.JspBase.service(JspBase.java:34)
        at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
        at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
        at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
        at weblogic.servlet.internal.ServletStubImpl.onAddToMapException(ServletStubImpl.java:408)
        at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:318)
        at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
        at weblogic.servlet.internal.RequestDispatcherImpl.invokeServlet(RequestDispatcherImpl.java:502)
        at weblogic.servlet.internal.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:251)
        at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:341)
        at org.apache.myfaces.application.jsp.JspViewHandlerImpl.buildView(JspViewHandlerImpl.java:486)
        at org.apache.myfaces.application.jsp.JspViewHandlerImpl.renderView(JspViewHandlerImpl.java:337)
        at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:41)
        at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:140)
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:155)

        2nd call :
        java.lang.Exception: Stack trace
        at java.lang.Thread.dumpStack(Thread.java:1206)
        at org.apache.myfaces.application.jsp.ViewResponseWrapper.getOutputStream(ViewResponseWrapper.java:116)
        at weblogic.servlet.internal.DelegateChunkWriter.getWriter(DelegateChunkWriter.java:153)
        at weblogic.servlet.internal.DelegateChunkWriter.flush(DelegateChunkWriter.java:132)
        at weblogic.servlet.internal.ChunkOutputWrapper.flush(ChunkOutputWrapper.java:171)
        at weblogic.servlet.jsp.JspWriterImpl.flush(JspWriterImpl.java:98)
        at org.apache.myfaces.taglib.core.ViewTag.doStartTag(ViewTag.java:96)
        at jsp_servlet.faces.face._jsptag0(_face.java:102)
        at jsp_servlet.faces.face._jspService(_face.java:75)
        at weblogic.servlet.jsp.JspBase.service(JspBase.java:34)
        at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
        at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
        at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
        at weblogic.servlet.internal.ServletStubImpl.onAddToMapException(ServletStubImpl.java:408)
        at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:318)
        at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
        at weblogic.servlet.internal.RequestDispatcherImpl.invokeServlet(RequestDispatcherImpl.java:502)
        at weblogic.servlet.internal.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:251)
        at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:341)

        Looking at the generated servlet __face.java, the 1st call (line 73) is the write of a carriage return \r\n in my faces.jsp preceding the <view> tag.
        The 2nd call is the flush() performs by the tag ViewTag itself when entering the doStartTag() (following JSFspecification)

        So ... the problem is a bit more complex, I hope it will help.

        Show
        Guillaume Menguy added a comment - I tried the solution above ( myfaces-core 1.2.6 patched with the MYFACES-1955 .patch ) under Weblogic 10.3 Unfortunately it does not work, an exception is now thrown by MyFaces itself : java.lang.IllegalStateException at org.apache.myfaces.application.jsp.ViewResponseWrapper.getWriter(ViewResponseWrapper.java:129) at org.apache.myfaces.taglib.core.ViewTag.doStartTag(ViewTag.java:100) at jsp_servlet. faces. face._jsp tag0( _face.java:102) at jsp_servlet. faces. face._jspService( _face.java:75) at weblogic.servlet.jsp.JspBase.service(JspBase.java:34) Apparently, before the view tag calls the getWriter() on the instance of ViewResponseWrapper, the other method getOutputStream() has already been called twice before (I added a logger on it) by MyFaces implementation and, as I understand in the code of ViewResponseWrapper, the same instance cannot work with both a CharArrayWriter and a OutputStream instantiated inside. Maybe it can help, I added a dumpStack() in the method public ServletOutputStream getOutputStream() throws IOException {.. } of ViewResponseWrapper to understand which parts of MyFaces are calling it before the view tag does a getWriter() 1st call: at java.lang.Thread.dumpStack(Thread.java:1206) at org.apache.myfaces.application.jsp.ViewResponseWrapper.getOutputStream(ViewResponseWrapper.java:116) at weblogic.servlet.internal.DelegateChunkWriter.write(DelegateChunkWriter.java:108) at weblogic.servlet.internal.ChunkOutputWrapper.write(ChunkOutputWrapper.java:139) at weblogic.servlet.jsp.JspWriterImpl.write(JspWriterImpl.java:274) at jsp_servlet. faces. face._jspService( _face.java:73) at weblogic.servlet.jsp.JspBase.service(JspBase.java:34) at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227) at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292) at weblogic.servlet.internal.ServletStubImpl.onAddToMapException(ServletStubImpl.java:408) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:318) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175) at weblogic.servlet.internal.RequestDispatcherImpl.invokeServlet(RequestDispatcherImpl.java:502) at weblogic.servlet.internal.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:251) at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:341) at org.apache.myfaces.application.jsp.JspViewHandlerImpl.buildView(JspViewHandlerImpl.java:486) at org.apache.myfaces.application.jsp.JspViewHandlerImpl.renderView(JspViewHandlerImpl.java:337) at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:41) at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:140) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:155) 2nd call : java.lang.Exception: Stack trace at java.lang.Thread.dumpStack(Thread.java:1206) at org.apache.myfaces.application.jsp.ViewResponseWrapper.getOutputStream(ViewResponseWrapper.java:116) at weblogic.servlet.internal.DelegateChunkWriter.getWriter(DelegateChunkWriter.java:153) at weblogic.servlet.internal.DelegateChunkWriter.flush(DelegateChunkWriter.java:132) at weblogic.servlet.internal.ChunkOutputWrapper.flush(ChunkOutputWrapper.java:171) at weblogic.servlet.jsp.JspWriterImpl.flush(JspWriterImpl.java:98) at org.apache.myfaces.taglib.core.ViewTag.doStartTag(ViewTag.java:96) at jsp_servlet. faces. face._jsp tag0( _face.java:102) at jsp_servlet. faces. face._jspService( _face.java:75) at weblogic.servlet.jsp.JspBase.service(JspBase.java:34) at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227) at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292) at weblogic.servlet.internal.ServletStubImpl.onAddToMapException(ServletStubImpl.java:408) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:318) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175) at weblogic.servlet.internal.RequestDispatcherImpl.invokeServlet(RequestDispatcherImpl.java:502) at weblogic.servlet.internal.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:251) at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:341) Looking at the generated servlet __face.java, the 1st call (line 73) is the write of a carriage return \r\n in my faces.jsp preceding the <view> tag. The 2nd call is the flush() performs by the tag ViewTag itself when entering the doStartTag() (following JSFspecification) So ... the problem is a bit more complex, I hope it will help.
        Hide
        Leonardo Uribe added a comment -

        After doing a lot of tests, the problem became clear:

        1st call:
        at java.lang.Thread.dumpStack(Thread.java:1206)
        at org.apache.myfaces.application.jsp.ViewResponseWrapper.getOutputStream(ViewResponseWrapper.java:116)
        at weblogic.servlet.internal.DelegateChunkWriter.write(DelegateChunkWriter.java:108)

        DelegateChunkWriter violates servlet spec, calling "getOutputStream" from "write" method. Myfaces is doing right, but weblogic do not. That is the reason why myfaces works well in other containers (they never call getOutputStream).

        Bad luck this time. It is a bug on weblogic.

        Show
        Leonardo Uribe added a comment - After doing a lot of tests, the problem became clear: 1st call: at java.lang.Thread.dumpStack(Thread.java:1206) at org.apache.myfaces.application.jsp.ViewResponseWrapper.getOutputStream(ViewResponseWrapper.java:116) at weblogic.servlet.internal.DelegateChunkWriter.write(DelegateChunkWriter.java:108) DelegateChunkWriter violates servlet spec, calling "getOutputStream" from "write" method. Myfaces is doing right, but weblogic do not. That is the reason why myfaces works well in other containers (they never call getOutputStream). Bad luck this time. It is a bug on weblogic.
        Hide
        Vasil Svetoslavov added a comment -

        Perhaps a bug should be filed on Oracle's bug tracking system...

        Show
        Vasil Svetoslavov added a comment - Perhaps a bug should be filed on Oracle's bug tracking system...
        Hide
        Matthias Weßendorf added a comment -

        I filed a bug against our internal bug database... stay tuned

        Show
        Matthias Weßendorf added a comment - I filed a bug against our internal bug database... stay tuned
        Hide
        Matthias Weßendorf added a comment -

        And thanks to Leonardo to track this down!

        Show
        Matthias Weßendorf added a comment - And thanks to Leonardo to track this down!
        Hide
        Leonardo Uribe added a comment -

        Trying to check this issue, the following facts appears:

        1. myfaces 1.2 + facelets works without problem. The bug does not appear, so this confirms the fact that this is a weblogic jsp compiler bug.

        2. There is a way to make work myfaces 1.2 + jsp on weblogic. I tried add this configuration to WEB-INF/weblogic.xml file:

        <weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-web-app.xsd http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

        <jsp-descriptor>
        <encoding>utf-8</encoding>
        </jsp-descriptor>

        </weblogic-web-app>

        The default encoding for jsp files is utf-8, but put this configuration triggers something inside weblogic jsp compiler that makes it work (the version tested was myfaces 1.2.6).

        The weblogic server version tested was 10.3. It could be good have confirmation if this works for other weblogic server versions. I hope this helps people that wants to use myfaces on weblogic.

        Show
        Leonardo Uribe added a comment - Trying to check this issue, the following facts appears: 1. myfaces 1.2 + facelets works without problem. The bug does not appear, so this confirms the fact that this is a weblogic jsp compiler bug. 2. There is a way to make work myfaces 1.2 + jsp on weblogic. I tried add this configuration to WEB-INF/weblogic.xml file: <weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-web-app.xsd http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd "> <jsp-descriptor> <encoding>utf-8</encoding> </jsp-descriptor> </weblogic-web-app> The default encoding for jsp files is utf-8, but put this configuration triggers something inside weblogic jsp compiler that makes it work (the version tested was myfaces 1.2.6). The weblogic server version tested was 10.3. It could be good have confirmation if this works for other weblogic server versions. I hope this helps people that wants to use myfaces on weblogic.
        Hide
        Matthias Weßendorf added a comment -

        Great workaround. I will update our internal Oracle bug with the new information

        Show
        Matthias Weßendorf added a comment - Great workaround. I will update our internal Oracle bug with the new information
        Hide
        Sergey Guriev added a comment -

        Workaround with weblogic.xml does not work for me. I'm using weblogic 10r3 and myfaces 1.2.6 without facelets.

        Show
        Sergey Guriev added a comment - Workaround with weblogic.xml does not work for me. I'm using weblogic 10r3 and myfaces 1.2.6 without facelets.
        Hide
        Leonardo Uribe added a comment -

        Could you attach an simple example to this issue, to check it and see why it doesn't work (It works for me on the same container)

        Show
        Leonardo Uribe added a comment - Could you attach an simple example to this issue, to check it and see why it doesn't work (It works for me on the same container)
        Hide
        Marco Brizi added a comment -

        I'm working on Weblogic server 10g3 and I'm trying to deploy the simple GuessNumber application provided by J2EE 5 tutorial (http://java.sun.com/javaee/5/docs/tutorial/doc/). Unfortunately I encountered the same problem of IllegalStateException and the encoding patch does not solve my error. In my last attempt I used myfaces in 1.2.7 release but the behavior is the same.
        Could you try if you have this problem with the same example I used? Thanks.

        Show
        Marco Brizi added a comment - I'm working on Weblogic server 10g3 and I'm trying to deploy the simple GuessNumber application provided by J2EE 5 tutorial ( http://java.sun.com/javaee/5/docs/tutorial/doc/ ). Unfortunately I encountered the same problem of IllegalStateException and the encoding patch does not solve my error. In my last attempt I used myfaces in 1.2.7 release but the behavior is the same. Could you try if you have this problem with the same example I used? Thanks.
        Hide
        Leonardo Uribe added a comment -

        After a full, very long and in deep review of this problem and the algorithm applied on JspViewHandler implementation, trying to find if a workaround for this issue is possible from myfaces side (it is a bug in weblogic but we have to live with it), a solution for this issue was found.

        The relevant parts of the algorithm are this:

        • buildView(): Set ViewResponseWrapper on
        • dispatch over wrapper. Only flushed the part before f:view. (here possible call to getOuputStream)
        • buildView(): Set ViewResponseWrapper off
        • Render view and flush over servlet response writer.
        • flush remaining part

        Note that at point 2, response.getOutputStream() has not been called but wrapper.getOutputStream(). In this point (call to flushToWrappedResponse() ), it is possible to try call flush through response.getWriter() instead, and prevent this error happening:

        try

        { _byteArrayWriter.writeTo(getResponse().getWriter(), getResponse().getCharacterEncoding()); }

        catch (IllegalStateException e)

        { getResponse().getOutputStream().write(_byteArrayWriter.toByteArray()); }

        This solution should work on all possible configurations of weblogic. I think the previous hack works only on servers deployed on machines with default encoding different than UTF-8.

        Show
        Leonardo Uribe added a comment - After a full, very long and in deep review of this problem and the algorithm applied on JspViewHandler implementation, trying to find if a workaround for this issue is possible from myfaces side (it is a bug in weblogic but we have to live with it), a solution for this issue was found. The relevant parts of the algorithm are this: buildView(): Set ViewResponseWrapper on dispatch over wrapper. Only flushed the part before f:view. (here possible call to getOuputStream) buildView(): Set ViewResponseWrapper off Render view and flush over servlet response writer. flush remaining part Note that at point 2, response.getOutputStream() has not been called but wrapper.getOutputStream(). In this point (call to flushToWrappedResponse() ), it is possible to try call flush through response.getWriter() instead, and prevent this error happening: try { _byteArrayWriter.writeTo(getResponse().getWriter(), getResponse().getCharacterEncoding()); } catch (IllegalStateException e) { getResponse().getOutputStream().write(_byteArrayWriter.toByteArray()); } This solution should work on all possible configurations of weblogic. I think the previous hack works only on servers deployed on machines with default encoding different than UTF-8.
        Hide
        Stanley Lin added a comment -

        Leonardo's UTF8 encoding workaround worked for me. I'm on WLS 11g and myfaces 1.1.

        Show
        Stanley Lin added a comment - Leonardo's UTF8 encoding workaround worked for me. I'm on WLS 11g and myfaces 1.1.
        Hide
        Jeffey Liu added a comment -

        Weblogic's Jsp Runtime uses response's outputstream to write template data and some container internal data to client due to some performance issues. I have reviewed the implementation for JspWriterImpl and its related class e.g: DelegateChunkWriter, and they do not violates the servlet spec. The servlet spec only forbid the user to mix both outputstream and writer. The jsp spec doesn't force the container to use response.getWriter, and it's the freedom of the container to choose either writer or outputstream to write information to client.

        The reason why this happened is that org.apache.myfaces.taglib.core.ViewTag's doStartTag(), it invokes flushContentToWrappedResponse(). It means if container invokes getOutputStream() on the instance of ViewHandlerResponseWrapper, then the wrapping response's getOutputStream() will be invoked. When flusing, the ViewHandlerResponseWrapper will flush the writer or outputstream to the real one, then it calls ServletResponse.getOutputStream. During the rendering phrase, the org.apache.myfaces.application.jsp.JspViewHandlerImpl always expects writer from response. This assumption will lead specification violation since getOutputStream() and getWriter() could not be mixed on HttpServletResponse.

        This is similar with the bug we filed for sun's ri. you can refer it here : https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=414

        For the fix, I suggest the ViewHandlerResponseWrapper uses only either the writer or outputstream of the servlet response, and not to use them together.

        I have reviewed the fix, and it is fine for weblogic. Thanks

        Show
        Jeffey Liu added a comment - Weblogic's Jsp Runtime uses response's outputstream to write template data and some container internal data to client due to some performance issues. I have reviewed the implementation for JspWriterImpl and its related class e.g: DelegateChunkWriter, and they do not violates the servlet spec. The servlet spec only forbid the user to mix both outputstream and writer. The jsp spec doesn't force the container to use response.getWriter, and it's the freedom of the container to choose either writer or outputstream to write information to client. The reason why this happened is that org.apache.myfaces.taglib.core.ViewTag's doStartTag(), it invokes flushContentToWrappedResponse(). It means if container invokes getOutputStream() on the instance of ViewHandlerResponseWrapper, then the wrapping response's getOutputStream() will be invoked. When flusing, the ViewHandlerResponseWrapper will flush the writer or outputstream to the real one, then it calls ServletResponse.getOutputStream. During the rendering phrase, the org.apache.myfaces.application.jsp.JspViewHandlerImpl always expects writer from response. This assumption will lead specification violation since getOutputStream() and getWriter() could not be mixed on HttpServletResponse. This is similar with the bug we filed for sun's ri. you can refer it here : https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=414 For the fix, I suggest the ViewHandlerResponseWrapper uses only either the writer or outputstream of the servlet response, and not to use them together. I have reviewed the fix, and it is fine for weblogic. Thanks

          People

          • Assignee:
            Leonardo Uribe
            Reporter:
            Paulo Moreira
          • Votes:
            5 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development