summaryrefslogtreecommitdiffstats
path: root/documentation/articles/UsingPolling.asciidoc
blob: 6889da048a03d6bdca82d3c8d866b4d979140f6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
---
title: Using Polling
order: 17
layout: page
---

[[using-polling]]
= Using Polling
To set up polling for your UI, you only need to set a poll interval
using `UI.setPollInterval(timeout)`. By doing this the browser will poll
the server each "timeout" ms and retrieve any possibly pending changes.
You can test this in practice by creating a small application which
initially creates a small "please wait" UI and then loads the actual UI
in a background thread.

[source,java]
....
public class PollingUI extends UI {

    @WebServlet(value = "/*")
    @VaadinServletConfiguration(productionMode = false, ui = Polling7UI.class)
    public static class Servlet extends VaadinServlet {
    }

    @Override
    protected void init(VaadinRequest request) {
        setContent(new Label("Loading data, please wait..."));
        setPollInterval(1000);
        new Thread(new Loader()).start();
    }

    class Loader implements Runnable {

        @Override
        public void run() {
            // Simulate a heavy database operation
            try {
                Thread.sleep(4500);
            } catch (InterruptedException e) {
            }

            // Wrap UI updates in access to properly deal with locking
            access(new Runnable() {
                @Override
                public void run() {
                    setContent(new Label("This is the real content"));

                    // Stop polling once the update is done
                    setPollInterval(-1);
                }
            });
        }
    }
}
....

For more information regarding locking the session, see [Using server
initiated events]

[[polling-for-multiple-components]]
Polling for multiple components
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you have the situation that several components need polling at some
point you should use some kind of Manager to handle the polling, for it
can only be set UI-wise (which makes perfectly sense)

A simple `UIPollingManager` which always uses the lowest registered
`intervalTime` could look like this:

[source,java]
....
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;

import com.vaadin.ui.UI;

public class UIPollingManager
{

    private Map<UI, Map<Object, Integer>> pollRequests;

    public UIPollingManager()
    {
        pollRequests = new WeakHashMap<>(); // Let's use weak references in case someone forgets to unregister properly
    }

    /**
     * Registers a poll request for the given UI. Sets the pollInterval of this UI to the lowest registered interval.
     * @param ui
     * @param requestor
     * @param pollIntervalInMillis poll interval in milliseconds
     */
    public void registerPollRequest(UI ui, Object requestor, int pollIntervalInMillis)
    {
        Map<Object, Integer> uiRequests = pollRequests.get(ui);
        if (uiRequests == null)
        {
            uiRequests = new HashMap<>();
            pollRequests.put(ui, uiRequests);
        }

        uiRequests.put(requestor, pollIntervalInMillis);

        setPollInterval(ui);
    }

    /**
     * Removes a poll request for the given UI (if existent). Sets the pollInterval of this UI to the lowest registered interval
     * remaining or -1 if no more requests exist for the UI
     * @param ui
     * @param requestor
     */
    public void unregisterPollRequest(UI ui, Object requestor)
    {
        Map<Object, Integer> uiRequests = pollRequests.get(ui);
        if (uiRequests != null)
        {
            uiRequests.remove(requestor);

            // Remove the UI from our map if no requests exist anymore
            if (uiRequests.size() <= 0) pollRequests.remove(ui);
        }

        setPollInterval(ui);
    }

    /**
     * Removes all poll requests of the given UI and sets the pollInterval to -1
     * @param ui
     */
    public void unregisterAllPollRequests(UI ui)
    {
        pollRequests.remove(ui);

        ui.setPollInterval(-1);
    }

    /**
     * Sets the pollInterval of the given UI to the lowest registered interval time of this UI
     * @param ui
     */
    private void setPollInterval(UI ui)
    {
        Map<Object, Integer> uiRequests = pollRequests.get(ui);
        if (uiRequests != null)
        {
            ui.setPollInterval(getLowestNumber(uiRequests.values()));
        }
    }

    /**
     * Returns the lowest number of a given Integer-Collection. Returns -1 if no valid Integer is included in the collection.
     * @param intervalArray
     * @return
     */
    private Integer getLowestNumber(Collection<Integer> intervalArray)
    {
        Integer lowestNum = null;

        for (Integer i : intervalArray)
        {
            if (i != null && ( lowestNum == null || i < lowestNum )) lowestNum = i;
        }

        if (lowestNum == null) return -1;
        else
            return lowestNum;
    }
}
....

The changed example could then look like this:

[source,java]
....
public class Polling7UI extends UI {

    private UIPollingManager pollingManager; // Instantiate this via Spring or get it via Singleton or whatever

    @WebServlet(value = "/*")
    @VaadinServletConfiguration(productionMode = false, ui = Polling7UI.class)
    public static class Servlet extends VaadinServlet {
    }

    @Override
    protected void init(VaadinRequest request) {
        setContent(new Label("Loading data, please wait..."));
        Loader loader = new Loader();
        pollingManager.registerPollRequest(this, loader, 1000);
        new Thread(loader).start();
    }

    class Loader implements Runnable {
        private UI ui;
        private UIPollingManager pollingManager;
        public Loader( UI ui, UIPollingManager pollingManager )
        {
            this.ui = ui;
            this.pollingManager = pollingManager;
        }

        @Override
        public void run() {
            // Simulate a heavy database operation
            try {
                Thread.sleep(4500);
            } catch (InterruptedException e) {
            }

            final Loader loader = this;
            // Wrap UI updates in access to properly deal with locking
            access(new Runnable() {
                @Override
                public void run() {
                    setContent(new Label("This is the real content"));

                    // Stop polling once the update is done
                    pollingManager.unregisterPollRequest(ui, loader);
                }
            });
        }
    }
}
....