[ DWR Website | Web Application Index ]

Server Side Reverse Ajax Clock

Creating a clock in a web page is easy, but what about a clock controlled by the server? This demo shows how use use a separate server side thread to control a number of browsers.

Client side script

Virtually none. Other than setting up the tabs, all we do is to turn active Reverse Ajax on: dwr.engine.setActiveReverseAjax(true);. Reverse Ajax will work without comet, by using piggyback, however this gives you very long latency, not what we need for a clock, so we turn on comet or polling (whatever the server is configured to prefer).

The server code uses a ScheduledThreadPoolExecutor to call update the screen once a second. The setClockDisplay looks like this:

String page = ServerContextFactory.get().getContextPath() + "/reverseajax/clock.html";
Browser.withPage(page, new Runnable()
{
    public void run()
    {
        Util.setValue("clockDisplay", output);
    }
});

ServerContextFactory is a lot like WebContextFactory, however it will work outside a DWR thread. Since we're using the ScheduledThreadPoolExecutor thread here, we need to use ServerContext and not WebContext.

We need to work out the page to update. You may know the contextPath without needing to ask, but in this case we're making the web-app relocatable by asking for the contextPath.

We then create a scope where the target browsers includes everyone looking at the given page, and we use the Util.setValue() method to alter the target browsers.

HTML source:

<input type="button" value="Start / Stop" onclick="Clock.toggle();"/>
<h2 id="clockDisplay"></h2>

Javascript source:

dwr.engine.setActiveReverseAjax(true);

Java source:

public class Clock implements Runnable {
    public Clock() {
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
        executor.scheduleAtFixedRate(this, 1, 1, TimeUnit.SECONDS);
    }

    public void run() {
        if (active) {
            setClockDisplay(new Date().toString());
        }
    }

    /**
     * Called from the client to turn the clock on/off
     */
    public synchronized void toggle() {
        active = !active;

        if (active) {
            setClockDisplay("Started");
        }
        else {
            setClockDisplay("Stopped");
        }
    }

    /**
     * Actually alter the clients.
     * @param output The string to display.
     */
    public void setClockDisplay(final String output) {
        String page = ServerContextFactory.get().getContextPath() + "/reverseajax/clock.html";
        Browser.withPage(page, new Runnable() {
            public void run() {
                Util.setValue("clockDisplay", output);
            }
        });
    }

    protected transient boolean active = false;
}