diff options
Diffstat (limited to 'server')
12 files changed, 412 insertions, 60 deletions
diff --git a/server/src/com/vaadin/server/LegacyCommunicationManager.java b/server/src/com/vaadin/server/LegacyCommunicationManager.java index e982cdf10a..87b484a65f 100644 --- a/server/src/com/vaadin/server/LegacyCommunicationManager.java +++ b/server/src/com/vaadin/server/LegacyCommunicationManager.java @@ -353,6 +353,10 @@ public class LegacyCommunicationManager implements Serializable { res.clear(); } + public boolean isEmpty() { + return res.isEmpty(); + } + } /** diff --git a/server/src/com/vaadin/server/LocaleService.java b/server/src/com/vaadin/server/LocaleService.java index 0274d227ab..ccdc49f690 100644 --- a/server/src/com/vaadin/server/LocaleService.java +++ b/server/src/com/vaadin/server/LocaleService.java @@ -23,6 +23,7 @@ import java.io.Serializable; import java.text.DateFormat; import java.text.DateFormatSymbols; import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Locale; import java.util.logging.Logger; @@ -120,9 +121,24 @@ public class LocaleService implements Serializable { LocaleData localeData = new LocaleData(); localeData.name = locale.toString(); + Calendar c = Calendar.getInstance(locale); + c.set(2015, 0, 1); + SimpleDateFormat shortMonthFormat = new SimpleDateFormat("MMM", locale); + SimpleDateFormat longMonthFormat = new SimpleDateFormat("MMMM", locale); + + int monthsInYear = c.getMaximum(Calendar.MONTH) + 1; + localeData.shortMonthNames = new String[monthsInYear]; + localeData.monthNames = new String[monthsInYear]; + for (int month = 0; month < monthsInYear; month++) { + c.set(Calendar.MONTH, month); + String shortMonth = shortMonthFormat.format(c.getTime()); + String longMonth = longMonthFormat.format(c.getTime()); + localeData.shortMonthNames[month] = shortMonth; + localeData.monthNames[month] = longMonth; + } + final DateFormatSymbols dfs = new DateFormatSymbols(locale); - localeData.shortMonthNames = dfs.getShortMonths(); - localeData.monthNames = dfs.getMonths(); + // Client expects 0 based indexing, DateFormatSymbols use 1 based localeData.shortDayNames = new String[7]; localeData.dayNames = new String[7]; diff --git a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java index 05e4f6479f..5c0d2e14d4 100644 --- a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java +++ b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java @@ -165,7 +165,7 @@ public class AtmospherePushConnection implements PushConnection { } else { try { Writer writer = new StringWriter(); - new UidlWriter().write(getUI(), writer, false, async); + new UidlWriter().write(getUI(), writer, async); sendMessage("for(;;);[{" + writer.toString() + "}]"); } catch (Exception e) { throw new RuntimeException("Push failed", e); diff --git a/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java index 65fb144810..f3d4b163ff 100644 --- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java +++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java @@ -29,6 +29,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.vaadin.server.ClientConnector; +import com.vaadin.server.Constants; import com.vaadin.server.JsonCodec; import com.vaadin.server.LegacyCommunicationManager; import com.vaadin.server.LegacyCommunicationManager.InvalidUIDLSecurityKeyException; @@ -40,6 +41,7 @@ import com.vaadin.server.VaadinService; import com.vaadin.server.VariableOwner; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.Connector; +import com.vaadin.shared.Version; import com.vaadin.shared.communication.LegacyChangeVariablesInvocation; import com.vaadin.shared.communication.MethodInvocation; import com.vaadin.shared.communication.ServerRpc; @@ -77,6 +79,8 @@ public class ServerRpcHandler implements Serializable { private final int syncId; private final JsonObject json; private final boolean resynchronize; + private final int clientToServerMessageId; + private String widgetsetVersion = null; public RpcRequest(String jsonString, VaadinRequest request) { json = JsonUtil.parse(jsonString); @@ -106,7 +110,19 @@ public class ServerRpcHandler implements Serializable { } else { resynchronize = false; } + if (json.hasKey(ApplicationConstants.WIDGETSET_VERSION_ID)) { + widgetsetVersion = json + .getString(ApplicationConstants.WIDGETSET_VERSION_ID); + } + if (json.hasKey(ApplicationConstants.CLIENT_TO_SERVER_ID)) { + clientToServerMessageId = (int) json + .getNumber(ApplicationConstants.CLIENT_TO_SERVER_ID); + } else { + getLogger() + .warning("Server message without client id received"); + clientToServerMessageId = -1; + } invocations = json.getArray(ApplicationConstants.RPC_INVOCATIONS); } @@ -149,6 +165,15 @@ public class ServerRpcHandler implements Serializable { } /** + * Gets the id of the client to server message + * + * @return the server message id + */ + public int getClientToServerId() { + return clientToServerMessageId; + } + + /** * Gets the entire request in JSON format, as it was received from the * client. * <p> @@ -161,6 +186,17 @@ public class ServerRpcHandler implements Serializable { public JsonObject getRawJson() { return json; } + + /** + * Gets the widget set version reported by the client + * + * @since 7.6 + * @return The widget set version reported by the client or null if the + * message did not contain a widget set version + */ + public String getWidgetsetVersion() { + return widgetsetVersion; + } } private static final int MAX_BUFFER_SIZE = 64 * 1024; @@ -199,8 +235,43 @@ public class ServerRpcHandler implements Serializable { rpcRequest.getCsrfToken())) { throw new InvalidUIDLSecurityKeyException(""); } - handleInvocations(ui, rpcRequest.getSyncId(), - rpcRequest.getRpcInvocationsData()); + + checkWidgetsetVersion(rpcRequest.getWidgetsetVersion()); + + int expectedId = ui.getLastProcessedClientToServerId() + 1; + if (rpcRequest.getClientToServerId() != -1 + && rpcRequest.getClientToServerId() != expectedId) { + // Invalid message id, skip RPC processing but force a full + // re-synchronization of the client as it might have not received + // the previous response (e.g. due to a bad connection) + + // Must resync also for duplicate messages because the server might + // have generated a response for the first message but the response + // did not reach the client. When the client re-sends the message, + // it would only get an empty response (because the dirty flags have + // been cleared on the server) and would be out of sync + ui.getSession().getCommunicationManager().repaintAll(ui); + + if (rpcRequest.getClientToServerId() < expectedId) { + // Just a duplicate message due to a bad connection or similar + // It has already been handled by the server so it is safe to + // ignore + getLogger().fine( + "Ignoring old message from the client. Expected: " + + expectedId + ", got: " + + rpcRequest.getClientToServerId()); + } else { + getLogger().warning( + "Unexpected message id from the client. Expected: " + + expectedId + ", got: " + + rpcRequest.getClientToServerId()); + } + } else { + // Message id ok, process RPCs + ui.setLastProcessedClientToServerId(expectedId); + handleInvocations(ui, rpcRequest.getSyncId(), + rpcRequest.getRpcInvocationsData()); + } ui.getConnectorTracker().cleanConcurrentlyRemovedConnectorIds( rpcRequest.getSyncId()); @@ -208,6 +279,29 @@ public class ServerRpcHandler implements Serializable { if (rpcRequest.isResynchronize()) { ui.getSession().getCommunicationManager().repaintAll(ui); } + + } + + /** + * Checks that the version reported by the client (widgetset) matches that + * of the server. + * + * @param widgetsetVersion + * the widget set version reported by the client or null + */ + private void checkWidgetsetVersion(String widgetsetVersion) { + if (widgetsetVersion == null) { + // Only check when the widgetset version is reported. It is reported + // in the first UIDL request (not the initial request as it is a + // plain GET /) + return; + } + + if (!Version.getFullVersion().equals(widgetsetVersion)) { + getLogger().warning( + String.format(Constants.WIDGETSET_MISMATCH_INFO, + Version.getFullVersion(), widgetsetVersion)); + } } /** diff --git a/server/src/com/vaadin/server/communication/UIInitHandler.java b/server/src/com/vaadin/server/communication/UIInitHandler.java index 3a6dc1e55f..f380a6df6e 100644 --- a/server/src/com/vaadin/server/communication/UIInitHandler.java +++ b/server/src/com/vaadin/server/communication/UIInitHandler.java @@ -282,7 +282,7 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { if (session.getConfiguration().isXsrfProtectionEnabled()) { writer.write(getSecurityKeyUIDL(session)); } - new UidlWriter().write(uI, writer, true, false); + new UidlWriter().write(uI, writer, false); writer.write("}"); String initialUIDL = writer.toString(); diff --git a/server/src/com/vaadin/server/communication/UidlRequestHandler.java b/server/src/com/vaadin/server/communication/UidlRequestHandler.java index 33a3669b7f..dda3d81453 100644 --- a/server/src/com/vaadin/server/communication/UidlRequestHandler.java +++ b/server/src/com/vaadin/server/communication/UidlRequestHandler.java @@ -22,7 +22,6 @@ import java.io.Writer; import java.util.logging.Level; import java.util.logging.Logger; -import com.vaadin.server.Constants; import com.vaadin.server.LegacyCommunicationManager.InvalidUIDLSecurityKeyException; import com.vaadin.server.ServletPortletHelper; import com.vaadin.server.SessionExpiredHandler; @@ -32,9 +31,7 @@ import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinResponse; import com.vaadin.server.VaadinService; import com.vaadin.server.VaadinSession; -import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.JsonConstants; -import com.vaadin.shared.Version; import com.vaadin.ui.UI; import elemental.json.JsonException; @@ -76,29 +73,12 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements return true; } - checkWidgetsetVersion(request); - // repaint requested or session has timed out and new one is created - boolean repaintAll; - - // TODO PUSH analyzeLayouts should be - // part of the message payload to make the functionality transport - // agnostic - - // Resynchronize is sent in the payload but will still support the - // parameter also for compatibility reasons - repaintAll = (request - .getParameter(ApplicationConstants.URL_PARAMETER_REPAINT_ALL) != null); - StringWriter stringWriter = new StringWriter(); try { rpcHandler.handleRpc(uI, request.getReader(), request); - if (repaintAll) { - session.getCommunicationManager().repaintAll(uI); - } - - writeUidl(request, response, uI, stringWriter, repaintAll); + writeUidl(request, response, uI, stringWriter); } catch (JsonException e) { getLogger().log(Level.SEVERE, "Error writing JSON to response", e); // Refresh on client side @@ -119,28 +99,6 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements stringWriter.toString()); } - /** - * Checks that the version reported by the client (widgetset) matches that - * of the server. - * - * @param request - */ - private void checkWidgetsetVersion(VaadinRequest request) { - String widgetsetVersion = request.getParameter("v-wsver"); - if (widgetsetVersion == null) { - // Only check when the widgetset version is reported. It is reported - // in the first UIDL request (not the initial request as it is a - // plain GET /) - return; - } - - if (!Version.getFullVersion().equals(widgetsetVersion)) { - getLogger().warning( - String.format(Constants.WIDGETSET_MISMATCH_INFO, - Version.getFullVersion(), widgetsetVersion)); - } - } - private void writeRefresh(VaadinRequest request, VaadinResponse response) throws IOException { String json = VaadinService.createCriticalNotificationJSON(null, null, @@ -149,10 +107,10 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements } private void writeUidl(VaadinRequest request, VaadinResponse response, - UI ui, Writer writer, boolean repaintAll) throws IOException { + UI ui, Writer writer) throws IOException { openJsonMessage(writer, response); - new UidlWriter().write(ui, writer, repaintAll, false); + new UidlWriter().write(ui, writer, false); closeJsonMessage(writer); } diff --git a/server/src/com/vaadin/server/communication/UidlWriter.java b/server/src/com/vaadin/server/communication/UidlWriter.java index a4797e49aa..25b1bdaaf9 100644 --- a/server/src/com/vaadin/server/communication/UidlWriter.java +++ b/server/src/com/vaadin/server/communication/UidlWriter.java @@ -63,8 +63,6 @@ public class UidlWriter implements Serializable { * The {@link UI} whose changes to write * @param writer * The writer to use - * @param repaintAll - * Whether the client should re-render the whole UI. * @param analyzeLayouts * Whether detected layout problems should be logged. * @param async @@ -74,8 +72,7 @@ public class UidlWriter implements Serializable { * @throws IOException * If the writing fails. */ - public void write(UI ui, Writer writer, boolean repaintAll, boolean async) - throws IOException { + public void write(UI ui, Writer writer, boolean async) throws IOException { VaadinSession session = ui.getSession(); VaadinService service = session.getService(); @@ -86,6 +83,8 @@ public class UidlWriter implements Serializable { Set<ClientConnector> processedConnectors = new HashSet<ClientConnector>(); LegacyCommunicationManager manager = session.getCommunicationManager(); + ClientCache clientCache = manager.getClientCache(ui); + boolean repaintAll = clientCache.isEmpty(); // Paints components ConnectorTracker uiConnectorTracker = ui.getConnectorTracker(); getLogger().log(Level.FINE, "* Creating response to client"); @@ -130,7 +129,14 @@ public class UidlWriter implements Serializable { .getCurrentSyncId() : -1; writer.write("\"" + ApplicationConstants.SERVER_SYNC_ID + "\": " + syncId + ", "); - + if (repaintAll) { + writer.write("\"" + ApplicationConstants.RESYNCHRONIZE_ID + + "\": true, "); + } + int nextClientToServerMessageId = ui + .getLastProcessedClientToServerId() + 1; + writer.write("\"" + ApplicationConstants.CLIENT_TO_SERVER_ID + + "\": " + nextClientToServerMessageId + ", "); writer.write("\"changes\" : "); JsonPaintTarget paintTarget = new JsonPaintTarget(manager, writer, @@ -202,7 +208,6 @@ public class UidlWriter implements Serializable { Collection<Class<? extends ClientConnector>> usedClientConnectors = paintTarget .getUsedClientConnectors(); boolean typeMappingsOpen = false; - ClientCache clientCache = manager.getClientCache(ui); List<Class<? extends ClientConnector>> newConnectorTypes = new ArrayList<Class<? extends ClientConnector>>(); diff --git a/server/src/com/vaadin/ui/PushConfiguration.java b/server/src/com/vaadin/ui/PushConfiguration.java index 90ad28542c..6eaf683d99 100644 --- a/server/src/com/vaadin/ui/PushConfiguration.java +++ b/server/src/com/vaadin/ui/PushConfiguration.java @@ -207,8 +207,14 @@ class PushConfigurationImpl implements PushConfiguration { @Override public Transport getTransport() { try { - return Transport + Transport tr = Transport .getByIdentifier(getParameter(PushConfigurationState.TRANSPORT_PARAM)); + if (tr == Transport.WEBSOCKET + && getState(false).alwaysUseXhrForServerRequests) { + return Transport.WEBSOCKET_XHR; + } else { + return tr; + } } catch (IllegalArgumentException e) { return null; } @@ -223,8 +229,16 @@ class PushConfigurationImpl implements PushConfiguration { */ @Override public void setTransport(Transport transport) { - setParameter(PushConfigurationState.TRANSPORT_PARAM, - transport.getIdentifier()); + if (transport == Transport.WEBSOCKET_XHR) { + getState().alwaysUseXhrForServerRequests = true; + // Atmosphere knows only about "websocket" + setParameter(PushConfigurationState.TRANSPORT_PARAM, + Transport.WEBSOCKET.getIdentifier()); + } else { + getState().alwaysUseXhrForServerRequests = false; + setParameter(PushConfigurationState.TRANSPORT_PARAM, + transport.getIdentifier()); + } } /* @@ -251,6 +265,10 @@ class PushConfigurationImpl implements PushConfiguration { */ @Override public void setFallbackTransport(Transport fallbackTransport) { + if (fallbackTransport == Transport.WEBSOCKET_XHR) { + throw new IllegalArgumentException( + "WEBSOCKET_XHR can only be used as primary transport"); + } setParameter(PushConfigurationState.FALLBACK_TRANSPORT_PARAM, fallbackTransport.getIdentifier()); } diff --git a/server/src/com/vaadin/ui/ReconnectDialogConfiguration.java b/server/src/com/vaadin/ui/ReconnectDialogConfiguration.java new file mode 100644 index 0000000000..92eb1e785f --- /dev/null +++ b/server/src/com/vaadin/ui/ReconnectDialogConfiguration.java @@ -0,0 +1,201 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.ui; + +import java.io.Serializable; + +/** + * Provides method for configuring the reconnect dialog. + * + * @since 7.6 + * @author Vaadin Ltd + */ +public interface ReconnectDialogConfiguration extends Serializable { + /** + * Gets the text to show in the reconnect dialog when trying to re-establish + * the server connection + * + * @return the text to show in the reconnect dialog + */ + public String getDialogText(); + + /** + * Sets the text to show in the reconnect dialog when trying to re-establish + * the server connection + * + * @param dialogText + * the text to show in the reconnect dialog + */ + public void setDialogText(String dialogText); + + /** + * Gets the text to show in the reconnect dialog after giving up trying to + * reconnect ({@link #getReconnectAttempts()} reached) + * + * @return the text to show in the reconnect dialog after giving up + */ + public String getDialogTextGaveUp(); + + /** + * Sets the text to show in the reconnect dialog after giving up trying to + * reconnect ({@link #getReconnectAttempts()} reached) + * + * @param dialogText + * the text to show in the reconnect dialog after giving up + */ + public void setDialogTextGaveUp(String dialogTextGaveUp); + + /** + * Gets the number of times to try to reconnect to the server before giving + * up + * + * @return the number of times to try to reconnect + */ + public int getReconnectAttempts(); + + /** + * Sets the number of times to try to reconnect to the server before giving + * up + * + * @param reconnectAttempts + * the number of times to try to reconnect + */ + public void setReconnectAttempts(int reconnectAttempts); + + /** + * Gets the interval (in milliseconds) between reconnect attempts + * + * @return the interval (in ms) between reconnect attempts + */ + public int getReconnectInterval(); + + /** + * Sets the interval (in milliseconds) between reconnect attempts + * + * @param reconnectInterval + * the interval (in ms) between reconnect attempts + */ + public void setReconnectInterval(int reconnectInterval); + + /** + * Gets the timeout (in milliseconds) between noticing a loss of connection + * and showing the dialog. + * + * @return the time to wait before showing a dialog + */ + public int getDialogGracePeriod(); + + /** + * Sets the timeout (in milliseconds) between noticing a loss of connection + * and showing the dialog. + * + * @param dialogGracePeriod + * the time to wait before showing a dialog + */ + public void setDialogGracePeriod(int dialogGracePeriod); + + /** + * Sets the modality of the dialog. + * <p> + * If the dialog is set to modal, it will prevent the usage of the + * application while the dialog is being shown. If not modal, the user can + * continue to use the application as normally and all server events will be + * queued until connection has been re-established. + * + * @param dialogModal + * true to make the dialog modal, false otherwise + */ + public void setDialogModal(boolean dialogModal); + + /** + * Checks the modality of the dialog. + * <p> + * + * @see #setDialogModal(boolean) + * @return true if the dialog is modal, false otherwise + */ + public boolean isDialogModal(); +} + +class ReconnectDialogConfigurationImpl implements ReconnectDialogConfiguration { + private UI ui; + + public ReconnectDialogConfigurationImpl(UI ui) { + this.ui = ui; + } + + @Override + public String getDialogText() { + return ui.getState(false).reconnectDialogConfiguration.dialogText; + } + + @Override + public void setDialogText(String dialogText) { + ui.getState().reconnectDialogConfiguration.dialogText = dialogText; + } + + @Override + public String getDialogTextGaveUp() { + return ui.getState(false).reconnectDialogConfiguration.dialogTextGaveUp; + } + + @Override + public void setDialogTextGaveUp(String dialogTextGaveUp) { + ui.getState().reconnectDialogConfiguration.dialogTextGaveUp = dialogTextGaveUp; + } + + @Override + public int getReconnectAttempts() { + return ui.getState(false).reconnectDialogConfiguration.reconnectAttempts; + } + + @Override + public void setReconnectAttempts(int reconnectAttempts) { + ui.getState().reconnectDialogConfiguration.reconnectAttempts = reconnectAttempts; + } + + @Override + public int getReconnectInterval() { + return ui.getState(false).reconnectDialogConfiguration.reconnectInterval; + } + + @Override + public void setReconnectInterval(int reconnectInterval) { + ui.getState().reconnectDialogConfiguration.reconnectInterval = reconnectInterval; + } + + @Override + public int getDialogGracePeriod() { + return ui.getState(false).reconnectDialogConfiguration.dialogGracePeriod; + } + + @Override + public void setDialogGracePeriod(int dialogGracePeriod) { + ui.getState().reconnectDialogConfiguration.dialogGracePeriod = dialogGracePeriod; + } + + @Override + public boolean isDialogModal() { + return ui.getState(false).reconnectDialogConfiguration.dialogModal; + } + + @Override + public void setDialogModal(boolean dialogModal) { + ui.getState().reconnectDialogConfiguration.dialogModal = dialogModal; + } + +} diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index 2129db614b..90ae713746 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -255,11 +255,19 @@ public abstract class UI extends AbstractSingleComponentContainer implements this); private PushConfiguration pushConfiguration = new PushConfigurationImpl( this); + private ReconnectDialogConfiguration reconnectDialogConfiguration = new ReconnectDialogConfigurationImpl( + this); private NotificationConfiguration notificationConfiguration = new NotificationConfigurationImpl( this); /** + * Tracks which message from the client should come next. First message from + * the client has id 0. + */ + private int lastProcessedClientToServerId = -1; + + /** * Creates a new empty UI without a caption. The content of the UI must be * set by calling {@link #setContent(Component)} before using the UI. */ @@ -1640,6 +1648,16 @@ public abstract class UI extends AbstractSingleComponentContainer implements } /** + * Retrieves the object used for configuring the reconnect dialog. + * + * @since 7.6 + * @return The instance used for reconnect dialog configuration + */ + public ReconnectDialogConfiguration getReconnectDialogConfiguration() { + return reconnectDialogConfiguration; + } + + /** * Get the label that is added to the container element, where tooltip, * notification and dialogs are added to. * @@ -1691,4 +1709,31 @@ public abstract class UI extends AbstractSingleComponentContainer implements public String getEmbedId() { return embedId; } + + /** + * Gets the last processed server message id. + * + * Used internally for communication tracking. + * + * @return lastProcessedServerMessageId the id of the last processed server + * message + * @since 7.6 + */ + public int getLastProcessedClientToServerId() { + return lastProcessedClientToServerId; + } + + /** + * Sets the last processed server message id. + * + * Used internally for communication tracking. + * + * @param lastProcessedServerMessageId + * the id of the last processed server message + * @since 7.6 + */ + public void setLastProcessedClientToServerId( + int lastProcessedClientToServerId) { + this.lastProcessedClientToServerId = lastProcessedClientToServerId; + } } diff --git a/server/src/com/vaadin/ui/Upload.java b/server/src/com/vaadin/ui/Upload.java index 693bd74dbf..2da7db53b5 100644 --- a/server/src/com/vaadin/ui/Upload.java +++ b/server/src/com/vaadin/ui/Upload.java @@ -121,6 +121,11 @@ public class Upload extends AbstractComponent implements Component.Focusable, public void change(String filename) { fireEvent(new ChangeEvent(Upload.this, filename)); } + + @Override + public void poll() { + // Nothing to do, called only to visit the server + } }); } diff --git a/server/tests/src/com/vaadin/ui/PushConfigurationTransportTest.java b/server/tests/src/com/vaadin/ui/PushConfigurationTransportTest.java index 305b2e06cd..80e7dd9261 100644 --- a/server/tests/src/com/vaadin/ui/PushConfigurationTransportTest.java +++ b/server/tests/src/com/vaadin/ui/PushConfigurationTransportTest.java @@ -40,6 +40,12 @@ public class PushConfigurationTransportTest { ui.getPushConfiguration().setTransport(transport); Assert.assertEquals(ui.getPushConfiguration().getTransport(), transport); + + if (transport == Transport.WEBSOCKET_XHR) { + Assert.assertTrue(ui.getState().pushConfiguration.alwaysUseXhrForServerRequests); + } else { + Assert.assertFalse(ui.getState().pushConfiguration.alwaysUseXhrForServerRequests); + } } } |