paintContent(target) and partial server-client updates

Hi there,

I am working on a custom component which may send large data sets to client widget. So far, most of components’ paintContent() methods are implemented as if the client widget is a new widget and all component’s data is sent to client. This behaviour can impact performance if the amount of data is large (i.e. contains HTML text like in my case).

My paintContent() method can be implemented so that it needs to send modified data for subsequent client updates. However, there is no way to ensure when to send full or partial update.

Take the following senario (FU: component sends full update, PU: component sends partial update):

  • Application is first rendered with the component rendering full update (FU)
  • User interacts with the component which trigger changes on server and the component update its status and send partial update (PU) since it knows the component was fully rendered previously.
  • User refreshes the page for no reason (hit F5), Vaadin will reconstruct the page from its current status but the component only send partial data update. This causes corrupted component state on client side.

The question: is there a way or mechanism in Vaadin that helps component to know when to send full updates again?

Any ideas or suggestion or alternatives are much appreciated.

Thanks,
Tien

Hi,

The core painting mechanism provides you no support here. We have kept the dirty flagging on component level to simplify our server and client side implementations. If you look at our ancient (ten year old) interfaces, we would have Paintable in addition to Component, which actually contains the paint method. But don’t try it, the current implementation don’t support using plain Paintables.

Although I gave this issue a chapter in my thesis about three years ago, so far we have made it well without. Most commonly the right cure is to split components into sub components (protected/package private if you want to hide their api). Although the AbstractComponent contains some extra API you might not like, the performance impact is quite minimal.

Although there is no support in the core, partial repaints can be done. And this might be a viable option in some cases. Tree and Table does this in the core, but to tell the truth I’d implement both with sub components if I’d start from the scratch today. Eg. in Tree when nodes are opened the server send only the nodes from the opened subtree. Table’s implementation is way too complicated for a good example.

A bit more complicated example implementation of partial repaints can be found from
OpenLayersMap
. It contains a very simple string key based internal dirty flagging system. In that class it was not to help with performance or bandwidth usage, but to help me in the battle with OpenLayers :-). But I’d guess this is a good starting point for you.

Also you might want to check Sami’s addon that might help you too (I’m not sure, I have never tried it):
http://vaadin.com/directory#addon/widget-rpc

cheers,
matti

Awesome, it works for me now.

Thanks a lot Matti. I took a leaf out of the
OpenLayersMap
book and it surprisingly works (even though I don’t understand why :grin::grin:).

To return the favour, I include my reuseable implementation of PartialPaintChecker.java:


/**
 * <p>
 * This class contains the logic necessary for those UI components which needs to perform partial server-client updates.
 * The component needs to have this as a private field and implement calls at key points (see all methods' javadocs).
 * </p>
 * <p>
 * Creditation: the main idea is obtained from
 * http://code.google.com/p/vopenlayers/source/browse/trunk/src/main/java/org/vaadin/vol/OpenLayersMap.java
 * </p>
 *
 * @since 0.2.9
 * @author ttran at coolersport.info
 **/
public class PartialPaintChecker
{
    private int dirtyFlags;
    private boolean partialRepaint = true;
    private boolean fullRepaint = true;
    private Paintable p;

    /**
     * <p>
     * Construct the checker only for this paintable.
     * </p>
     *
     * @param paintable
     *            dedicated paintable
     **/
    public PartialPaintChecker(final Paintable paintable)
    {
        p = paintable;
    }

    /**
     * <p>
     * Check if a partial repaint is needed instead of full repaint.
     * </p>
     *
     * @return false if full repaint is required or no flag was marked as dirty, true otherwise
     **/
    public boolean isPartialRepaint()
    {
        if (fullRepaint)
            return false;
        return dirtyFlags > 0;
    }

    /**
     * <p>
     * This method is meant to be called inside overridden paintContent() method to determine if a flag is marked as
     * dirty to send relevant update to client. Developer can rely on this method to decide when to send updates for
     * relevant data.
     * </p>
     *
     * @param flag
     *            flag to check
     * @return false if the flag was not marked as dirty, true otherwise (i.e. full repaint is needed or no flag was
     *         marked as dirty)
     **/
    public boolean isDirty(final int flag)
    {
        if (fullRepaint || dirtyFlags == 0)
            return true;
        return (dirtyFlags & flag) > 0;
    }

    /**
     * <p>
     * Indicate if a flag is dirty and needs to do a partial repaint. If a full repaint is not in progress,
     * {@link #partialPaint()} will be triggered and eventually call {@link Paintable#requestRepaint()}.
     * </p>
     * <p>
     * Developer may explicitly call {@link Paintable#requestRepaint()} after calling this method to enforce a full
     * repaint.
     * </p>
     *
     * @param flag
     *            flag to set as dirty, flags are stored using bit-comparison so ensure its value is a binary-bit like:
     *            1, 2, 4, 8, 16, 32, and so on
     **/
    public void setDirty(final int flag)
    {
        if (!fullRepaint)
        {
            dirtyFlags |= flag;
            partialPaint();
        }
    }

    /**
     * <p>
     * The paintable must override paintContent() method and call this method at very end of the method.
     * </p>
     **/
    public void paintContentPerformed()
    {
        clearDirtyFlags();
        fullRepaint = false;
    }

    /**
     * <p>
     * The paintable must override {@link Paintable#requestRepaint()} method and call this method at very beginning of
     * the method.
     * </p>
     **/
    public void checkBeforeRequestRepaint()
    {
        if (!partialRepaint)
        {
            clearDirtyFlags();
            fullRepaint = true;
        }
    }

    private void clearDirtyFlags()
    {
        dirtyFlags = 0;
    }

    private void partialPaint()
    {
        partialRepaint = true;
        try
        {
            p.requestRepaint();
        }
        finally
        {
            partialRepaint = false;
        }
    }
}

Nice! With javadocs and all. I’d bet it will be used by several vaadin developer. Now we should wrap that into a vaadin addon and share it for the community via
Directory
. I’m not that confident that the next component developer will find it via forum.

cheers,
matti