1

I know there has been numerous questions here on this question, but almost all of them suggest adding the following code because there is another layer "above" the FullAjaxExceptionHandler that is sending a plain redirect instead of doing an Ajax redirect (see this similar question):

if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
// JSF ajax request. Return special XML response which instructs JavaScript that it should in turn perform a redirect.
response.setContentType("text/xml");
response.getWriter()
    .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
    .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", loginURL);
} else {
    // Normal request. Perform redirect as usual.
    response.sendRedirect(loginURL);
}

My question is that I'm simply configuring Omnifaces's FullAjaxExceptionHandler to do all the error handling, I do not have Spring Security or container managed security that is intercepting the request before FullAjaxExceptionHandler can do it's thing. I can breakpoint into FullAjaxExceptionHandler and see that when the following lines of code is executed, my error page is still not being redirected.

String viewId = Faces.normalizeViewId(errorPageLocation);
ViewHandler viewHandler = context.getApplication().getViewHandler();
UIViewRoot viewRoot = viewHandler.createView(context, viewId);
context.setViewRoot(viewRoot);
context.getPartialViewContext().setRenderAll(true);
        ...
    context.renderResponse();

Instead, the Ajax request where the exception originated has this in it's response body:

<?xml version='1.0' encoding='UTF-8'?>
    <partial-response>
        <changes>
            <update id="javax.faces.ViewRoot"><![CDATA[<html xmlns="http://www.w3.org/1999/xhtml">... html of error page here ... </html>]]></update>
            <update id="javax.faces.ViewState"><![CDATA[-3527653129719750158:5595502883804776498]]></update>
        </changes>
    </partial-response>

It looks like FullAjaxExceptionHandler isn't doing what it's supposed to do, or am I missing something?

Update

Attaching browser JS output console screen cap.JS output console

Problem Identified

Turns out that the HTML of my error page is malformed, it contains the following snippet, which results in the mismatched tag error in the browser:

<script type="text/javascript">
//<![CDATA[
scrollTo(0, 0);
//]]>
</script>

This seemed to have closed the CDATA tag prematurely. This HTML was a result of the <h:outputScript/> tag, which I removed since I don't really need it.

Community
  • 1
  • 1
citress
  • 889
  • 3
  • 13
  • 35
  • Which PrimeFaces version? Older versions had trouble with `@all`: https://code.google.com/p/omnifaces/wiki/KnownIssues#PrimeFaces_2.0-3.1 To exclude at least PrimeFaces (and its bundled jQuery) from being the cause, what if you use `` instead of ``? Ajax response looks completely fine by the way. So until that step everything is well. It's just not been applied on the current HTML document by JavaScript for some reason so the problem is essentially in JS side. It could also happen if JS context has some error/conflict. Have you checked the JS console? – BalusC Sep 03 '13 at 16:28
  • I'm using PF3.5. The only error I see in my console is that it has failed to parse the partial update. I will update my post with the console screen capture. I changed from using a PF button to and indeed, I was redirected to the error page as expected. I'm not sure if it's something I can fix on my end, do you? – citress Sep 03 '13 at 16:52
  • Okay, this is thus a PF problem. Before posting an answer, I'd like to know which browser you're using and also if you have a `` or perhaps ``. – BalusC Sep 03 '13 at 16:55
  • Oh it's fixed! The HTML for my error page is malformed, so the wrong closing tag is a valid error. The closing tag comes from this line in my errorPage.xhtml: scrollTo(0, 0); – citress Sep 03 '13 at 17:00
  • I don't need it, so I removed it and it works now! Please post an answer, thanks for pointing me to the right direction! – citress Sep 03 '13 at 17:01
  • This is strange. It's supposed to work just fine. As to the CDATA nested inside the script element, MyFaces is known to do that implicitly, but I don't have had any problems with the current versions. Are you indeed using MyFaces instead of Mojarra? If so, perhaps you were using an old MyFaces version which has a bug that the nested CDATA isn't properly escaped? Note that I usually don't post answers as long as I can't explain the cause of the problem. – BalusC Sep 03 '13 at 17:10
  • I am using Mojarra actually. The issue is that CDATA tags cannot be nested (see http://stackoverflow.com/questions/223652/is-there-a-way-to-escape-a-cdata-end-token-in-xml). The HTML for my error page is inside of a CDATA, and in it, contains a script tag whose contents is again in a CDATA tag. So the nested end tag closed the CDATA element prematurely and thus, mismatched tags error results. – citress Sep 03 '13 at 18:15
  • You're right, they cannot be nested and should not be emitted at all. But which Mojarra version are you using? OmniFaces showcase web application has been thoroughly tested on almost every Mojarra version since 2.1.10 and I haven't seen this issue before. I've so far only seen MyFaces emitting those CDATA tags inside elements. – BalusC Sep 03 '13 at 18:19
  • I'm using Mojarra v2.1.24. – citress Sep 03 '13 at 19:22

2 Answers2

2

Many years after the original question, now using Wildfly 15, JSF 2.3, OmniFaces 3.2, I stumbled upon a similar issue: Malformed partial response from the FullAjaxExceptionHandler in case of an exception during an ajax call. The cause was a nested CDATA in the response, thus commenting out a part of the response, resulting in a XML parse error. The culprit appeared to be the JSF tag ui:debug. I have removed the statement and now it works as intended.

Jaap Reitsma
  • 171
  • 2
  • 7
1

The ajax response looks completely fine, it's having an <update id="javax.faces.ViewRoot"> containing the whole error page document, so the FullAjaxExceptionHandler did its job properly.

Your concrete problem is more likely caused in the client side or even in the error page document itself, after the ajax response has been retrieved. It's then JavaScript's turn to parse that ajax response and replace the current HTML document accordingly. Checking the browser's JavaScript console should give any clues as to problems during that step. In your particular case, the problem seems to be caused by a nested CDATA block around the content rendered by <h:outputScript> which in turn caused a JavaScript parsing error.

Unfortunately, I can't reproduce the problem with any Mojarra version I've at hands. Perhaps you've somewhere a custom/3rd party script renderer who's responsible for adding that CDATA block. That script renderer should skip the CDATA block when PartialViewContext#isAjaxRequest() returns true. If you still can't figure it out, then your best bet is to replace the <h:outputScript> by a plain HTML <script> or even to remove it altogether — as you ultimately did.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Did you test it with Mojarra 2.1.24? In any case, it looks like I might still need the javascript on my error page, thanks for the workaround. – citress Sep 04 '13 at 00:59