From: Leif Åstrand Date: Wed, 10 Apr 2013 07:21:59 +0000 (+0300) Subject: Don't process push messages until init JSON is processed (#11529) X-Git-Tag: 7.1.0.beta1~134 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=6f593d5847389edfc9dbb7bb65114dc4be6066ae;p=vaadin-framework.git Don't process push messages until init JSON is processed (#11529) * The test is not running reliably in all browsers, but assuming this is a symptom of other push issues and not related to this particular bug. Change-Id: I848b57502aa01467b0f60624cf599247ec76f32f --- diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index 0341a9d5c4..2fa82c6004 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -183,6 +183,19 @@ public class ApplicationConnection { protected boolean applicationRunning = false; + /** + * Keep track of whether the initialization JSON has been handled. We should + * not process any push messages until the initial JSON has been processed. + */ + private boolean initJsonHandled = false; + + /** + * Keep track of any push messages that arrive before + * {@link #initJsonHandled} is set to true. + */ + private JsArrayString incommingPushMessageQueue = JsArrayString + .createArray().cast(); + private boolean hasActiveRequest = false; /** @@ -1114,6 +1127,26 @@ public class ApplicationConnection { checkForPendingVariableBursts(); runPostRequestHooks(configuration.getRootPanelId()); } + + if (!initJsonHandled) { + /* + * Assume that the first request that is fully handled is the one + * with the initialization data. + */ + initJsonHandled = true; + + int queueLength = incommingPushMessageQueue.length(); + if (queueLength > 0) { + VConsole.log("Init handled, processing " + queueLength + + " enqueued messages"); + for (int i = 0; i < queueLength; i++) { + handlePushMessage(incommingPushMessageQueue.get(i)); + } + incommingPushMessageQueue.setLength(0); + } + + } + // deferring to avoid flickering Scheduler.get().scheduleDeferred(new Command() { @Override @@ -1258,6 +1291,14 @@ public class ApplicationConnection { return; } + /* + * Lock response handling to avoid a situation where something pushed + * from the server gets processed while waiting for e.g. lazily loaded + * connectors that are needed for processing the current message. + */ + final Object lock = new Object(); + suspendReponseHandling(lock); + VConsole.log("Handling message from server"); eventBus.fireEvent(new ResponseHandlingStartedEvent(this)); @@ -1476,6 +1517,7 @@ public class ApplicationConnection { // not sent asynchronously endRequest(); } + resumeResponseHandling(lock); if (Profiler.isEnabled()) { Scheduler.get().scheduleDeferred(new ScheduledCommand() { @@ -3264,11 +3306,19 @@ public class ApplicationConnection { * suspended. */ private void handlePendingMessages() { - for (PendingUIDLMessage pending : pendingUIDLMessages) { - handleUIDLMessage(pending.getStart(), pending.getJsonText(), - pending.getJson()); + if (!pendingUIDLMessages.isEmpty()) { + /* + * Clear the list before processing enqueued messages to support + * reentrancy + */ + List pendingMessages = pendingUIDLMessages; + pendingUIDLMessages = new ArrayList(); + + for (PendingUIDLMessage pending : pendingMessages) { + handleReceivedJSONMessage(pending.getStart(), + pending.getJsonText(), pending.getJson()); + } } - pendingUIDLMessages.clear(); } private boolean handleErrorInDelegate(String details, int statusCode) { @@ -3348,6 +3398,11 @@ public class ApplicationConnection { } public void handlePushMessage(String message) { - handleJSONText(message, 200); + if (initJsonHandled) { + handleJSONText(message, 200); + } else { + VConsole.log("Enqueuing push message has init has not yet been handled"); + incommingPushMessageQueue.push(message); + } } } diff --git a/uitest/src/com/vaadin/tests/push/PushFromInit.html b/uitest/src/com/vaadin/tests/push/PushFromInit.html new file mode 100644 index 0000000000..d009eb3baf --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushFromInit.html @@ -0,0 +1,32 @@ + + + + + + +New Test + + + + + + + + + + + + + + + + + + + + + + +
New Test
open/run-push/com.vaadin.tests.push.PushFromInit?debug&restartApplication
waitForTextvaadin=runpushcomvaadintestspushPushFromInit::PID_SLog_row_11. Logged in init
assertTextvaadin=runpushcomvaadintestspushPushFromInit::PID_SLog_row_02. Logged from background thread started in init
+ + diff --git a/uitest/src/com/vaadin/tests/push/PushFromInit.java b/uitest/src/com/vaadin/tests/push/PushFromInit.java new file mode 100644 index 0000000000..c43739ec04 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushFromInit.java @@ -0,0 +1,36 @@ +package com.vaadin.tests.push; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.Button; + +public class PushFromInit extends AbstractTestUIWithLog { + + @Override + protected void setup(VaadinRequest request) { + new Thread() { + @Override + public void run() { + runSafely(new Runnable() { + @Override + public void run() { + log("Logged from background thread started in init"); + } + }); + } + }.start(); + log("Logged in init"); + addComponent(new Button("Sync")); + } + + @Override + protected String getTestDescription() { + return "Pusing something to a newly created UI should not cause race conditions"; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(11529); + } + +}