简体   繁体   中英

How can I avoid a partial http response flush of large JSF views?

Today I've spend several hours reproducing a very strange UI behavior in our web application using JSF facelets: In some cases the UI was partially rendered in the web browser before the server side really finished rendering the whole view.

In the end it all came down to an JSF view with a large number of elements – in my case items of a submenu. There seems to be some threshold that triggers a partial flush of the response.

Here is a minimized example that visually demonstrates that effect:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="de" xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
    <style>
        td {
            vertical-align: top;
        }
    </style>
</h:head>
<h:body>

    <h1>EURNEU-10056</h1>

    <table>
        <tr>
            <td>
                <ol>
                    <ui:repeat value="#{bean.strings(10)}" var="str">
                        <li><h:outputText value="#{str}" /></li>
                    </ui:repeat>
                </ol>
                <h:outputText value="#{bean.delay(2000)}" />
            </td>
            <td>
                <ol>
                    <ui:repeat value="#{bean.strings(10)}" var="str">
                        <li><h:outputText value="#{str}" /></li>
                    </ui:repeat>
                </ol>
                <h:outputText value="#{bean.delay(2000)}" />
            </td>
            <td><ol>
                    <ui:repeat value="#{bean.strings(10)}" var="str">
                        <li><h:outputText value="#{str}" /></li>
                    </ui:repeat>
                </ol>
                <h:outputText value="#{bean.delay(2000)}" />
            </td>
        </tr>
    </table>

</h:body>
</html>

That simple view uses the following bean to generate a certain amount of strings and adds some artificial delays into the rendering of 2000ms after each of the 3 columns.

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.faces.bean.ManagedBean;

@ManagedBean
public class Bean implements Serializable {

    private static final long serialVersionUID = 1L;

    public List<String> strings(int count) {
        List<String> all = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            all.add(UUID.randomUUID().toString());
        }
        return all;
    }

    public String delay(int delay) {
        try {
            Thread.sleep(delay);
        }
        catch (InterruptedException ex) {
            // NOP;
        }
        return String.format("This string has been delayed for %d ms!", delay);
    }

}

The browsers shows the following phases while processing the request:

部分渲染 另一个局部渲染 最终渲染

If I lower the amount of strings used while generating the view the response is only flushed at the very end of the render phase.

Is there anything I can do to avoid that partial rendering? (other than lowering the number of elements)

PS: We are using JBoss EAP v7.0.9 as a server. The application itself is quite complex.

It turned our that explizit defining of Facelets buffer-size in web.xml solves that problem.

<!-- We raise the buffer size to avoid partial rendering of complex pages. -->
<context-param>
    <param-name>javax.faces.FACELETS_BUFFER_SIZE</param-name>
    <param-value>1024000</param-value>
</context-param>

That setting and the structure of the generated HTML define the very moment, the browser starts to render the response. In our case the menu was already renderable and showed much earlier than expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM