Affects Version/s: None
Chapter 7 of the JSR 329 Spec titled "WriteBehindResponse" was written to specify requirements for the bridge to support "after view content," meaning plain HTML markup in a JavaServer Pages (JSP) view that is found after the closing </f:view> tag. For example:
Chapter 7 of the JSR 329 Spec correctly states:
To preserve the natural order (of literal strings/static html or jsp/java rendered markup) in a JSP, Faces 1.2 utilizes an implementation dependent write behind mechanism ...
Chapter 7 also correctly states:
the JSF specification prescribes this (write behind) behavior without formalizing the mechanism
However, Chapter 7 then incorrectly states that:
the bridge must (formalize the mechanism).
In order to understand the root of the problem, refer to the com.sun.faces.application.ViewHandlerImpl#executePageToBuildView(FacesContext,UIViewRoot) method which decorates the response in the javax.faces.context.ExternalContext with com.sun.faces.application.ViewHandlerResponseWrapper. Since ViewHandlerResponseWrapper extends javax.servlet.http.HttpServletResponseWrapper, the Mojarra implementation introduces a dependency on the Servlet API that can cause the bridge to encounter a ClassCastException from javax.portlet.PortletResponse to javax.servlet.http.HttpServletResponse. The Apache MyFaces implementation does the same type of thing, and also decorates the request in the javax.faces.context.ExternalContext causing a ClassCastException from javax.portlet.PortletRequest to javax.servlet.http.HttpServletRequest.
Although the Liferay Faces Bridge implementation of JSR 329 passes 100% of the TCK tests, it is able to rely entirely on the Mojarra/MyFaces implementations to execute the "write behind" feature, thereby supporting "after view content" in a JSF portlet environment. It does this by decorating the PortletRequest with a wrapper that also implements HttpServletRequest. Similarly, it decorates the PortletResponse with a wrapper that also implements HttpServletResponse. To prove that this works, the bridge's BridgeWriteBehindResponseRenderImpl.java and BridgeWriteBehindResponseResourceImpl.java classes implement javax.portlet.faces.BridgeWriteBehindResponse but all the methods throw an UnsupportedOperationException. Since those methods never get called, the UnsupportedOperationException does not cause TCK failures.
This issue serves as a proposal for the following:
- Delete the requirements in chapter 7 of the Spec titled "WriteBehindResponse"
- Delete the associated API:
- Methods getWriteBehindRenderResponseWrapper() and getWriteBehindResourceResponseWrapper() from BridgeConfig.java and BridgeConfigWrapper.java (see FACES-2595)
- Delete the associated TCK Tests:
- bridge-tck-main-portlet: TestPage002 (renderPolicyTest)
- bridge-tck-main-portlet: TestPage200 (hasRenderContentAfterViewAttributeTest)
- bridge-tck-main-portlet: TestPage201 (renderContentAfterViewTest)
- bridge-tck-main-portlet: TestPage202 (implementsBridgeWriteBehindResponseTest)
- bridge-tck-render-policy1-portlet (in its entirety)
- bridge-tck-render-policy2-portlet (in its entirety)
- bridge-tck-render-policy3-portlet (in its entirety)
- Author a simple new test that proves that the bridge implementation invokes the JSF runtime in order to support "after view markup."
Although these are technically "breaking changes" to the API, the BridgeWriteBehindResponse interface and the aforementioned constants were only intended to be referenced by bridge implementations internally, and never intended to be referenced by JSF portlet developers in their JSF portlet applications.