From 735f0748344d7ee594c4e52a715d867dfdb23cb1 Mon Sep 17 00:00:00 2001 From: Tapio Aali Date: Mon, 9 Feb 2015 15:37:41 +0200 Subject: [PATCH] Make push path configurable (#14432). In order to use websockets with Weblogic 12.1.2 or later, push path 'ws' needs to be used instead of 'PUSH'. Change-Id: Ia90d11c20a375cef9cf4a53986a70d616a83db06 --- WebContent/WEB-INF/web.xml | 22 +++++- .../AtmospherePushConnection.java | 15 ++-- push/build.xml | 2 +- push/ivy.xml | 2 +- server/src/com/vaadin/server/Constants.java | 5 +- .../DefaultDeploymentConfiguration.java | 19 +++++ .../server/DeploymentConfiguration.java | 10 ++- .../vaadin/server/ServletPortletHelper.java | 3 +- .../server/communication/UIInitHandler.java | 5 +- .../src/com/vaadin/ui/PushConfiguration.java | 47 ++++++++++- .../AbstractDeploymentConfigurationTest.java | 4 + .../util/MockDeploymentConfiguration.java | 6 ++ .../vaadin/shared/ApplicationConstants.java | 12 ++- .../src/com/vaadin/shared/ui/ui/UIState.java | 1 + .../launcher/ApplicationRunnerServlet.java | 9 ++- .../src/com/vaadin/tests/push/PushPath.java | 77 +++++++++++++++++++ .../com/vaadin/tests/push/PushPathTest.java | 41 ++++++++++ 17 files changed, 253 insertions(+), 27 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/push/PushPath.java create mode 100644 uitest/src/com/vaadin/tests/push/PushPathTest.java diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml index ef60364202..c1102f4682 100644 --- a/WebContent/WEB-INF/web.xml +++ b/WebContent/WEB-INF/web.xml @@ -87,9 +87,9 @@ - + VaadinApplicationRunnerWithTimeoutRedirect com.vaadin.launcher.ApplicationRunnerServlet @@ -115,6 +115,17 @@ true + + + VaadinApplicationRunnerWithPushPathTest + com.vaadin.launcher.ApplicationRunnerServlet + + pushPath + ws + + true + + Embed App 1 /embed1/* @@ -148,6 +159,11 @@ /run-push/* + + VaadinApplicationRunnerWithPushPathTest + /run-pushpath/* + + IntegrationTest /integration/* diff --git a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java index da08928f36..a3a8caa1b4 100644 --- a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java +++ b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java @@ -41,7 +41,7 @@ import elemental.json.JsonObject; /** * The default {@link PushConnection} implementation that uses Atmosphere for * handling the communication channel. - * + * * @author Vaadin Ltd * @since 7.1 */ @@ -133,6 +133,8 @@ public class AtmospherePushConnection implements PushConnection { */ private Command pendingDisconnectCommand; + private String pushPath; + public AtmospherePushConnection() { } @@ -160,6 +162,9 @@ public class AtmospherePushConnection implements PushConnection { pushConfiguration.parameters.get(param)); } + pushPath = pushConfiguration.pushPath; + assert pushPath != null; + runWhenAtmosphereLoaded(new Command() { @Override public void execute() { @@ -176,7 +181,7 @@ public class AtmospherePushConnection implements PushConnection { private void connect() { String baseUrl = connection .translateVaadinUri(ApplicationConstants.APP_PROTOCOL_PREFIX - + ApplicationConstants.PUSH_PATH + '/'); + + pushPath + '/'); String extraParams = UIConstants.UI_ID_PARAMETER + "=" + connection.getConfiguration().getUIId(); @@ -251,9 +256,9 @@ public class AtmospherePushConnection implements PushConnection { /** * Called whenever a server push connection is established (or * re-established). - * + * * @param response - * + * * @since 7.2 */ protected void onConnect(AtmosphereResponse response) { @@ -342,7 +347,7 @@ public class AtmospherePushConnection implements PushConnection { /** * Called if the push connection fails. Atmosphere will automatically retry * the connection until successful. - * + * */ protected void onError(AtmosphereResponse response) { state = State.DISCONNECTED; diff --git a/push/build.xml b/push/build.xml index 9afe76620c..4e180fa03d 100644 --- a/push/build.xml +++ b/push/build.xml @@ -18,7 +18,7 @@ location="${result.dir}/js/VAADIN/vaadinPush.debug.js" /> - + diff --git a/push/ivy.xml b/push/ivy.xml index b899b34af7..b8d943f176 100644 --- a/push/ivy.xml +++ b/push/ivy.xml @@ -1,7 +1,7 @@ - + ]> diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java index 8036490333..b20b8004a5 100644 --- a/server/src/com/vaadin/server/Constants.java +++ b/server/src/com/vaadin/server/Constants.java @@ -67,7 +67,7 @@ public interface Constants { // Keep the version number in sync with push/build.xml and other locations // listed in that file - static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "2.2.4.vaadin2"; + static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "2.2.4.vaadin3"; static final String INVALID_ATMOSPHERE_VERSION_WARNING = "\n" + "=================================================================\n" @@ -132,11 +132,12 @@ public interface Constants { static final String SERVLET_PARAMETER_RESOURCE_CACHE_TIME = "resourceCacheTime"; static final String SERVLET_PARAMETER_HEARTBEAT_INTERVAL = "heartbeatInterval"; static final String SERVLET_PARAMETER_CLOSE_IDLE_SESSIONS = "closeIdleSessions"; - static final String SERVLET_PARAMETER_PUSH_MODE = "pushMode"; static final String SERVLET_PARAMETER_UI_PROVIDER = "UIProvider"; static final String SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING = "legacyPropertyToString"; static final String SERVLET_PARAMETER_SYNC_ID_CHECK = "syncIdCheck"; static final String SERVLET_PARAMETER_SENDURLSASPARAMETERS = "sendUrlsAsParameters"; + static final String SERVLET_PARAMETER_PUSH_MODE = "pushMode"; + static final String SERVLET_PARAMETER_PUSH_PATH = "pushPath"; // Configurable parameter names static final String PARAMETER_VAADIN_RESOURCES = "Resources"; diff --git a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java index b26e048431..5402979be8 100644 --- a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java +++ b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java @@ -61,6 +61,13 @@ public class DefaultDeploymentConfiguration extends public static final boolean DEFAULT_SEND_URLS_AS_PARAMETERS = true; + /** + * Default value for {@link #getPushPath()} = {@value} . + * + * @since 7.4.1 + */ + public static final String DEFAULT_PUSH_PATH = "PUSH"; + private final Properties initParameters; private boolean productionMode; private boolean xsrfProtectionEnabled; @@ -284,6 +291,18 @@ public class DefaultDeploymentConfiguration extends return initParameters; } + /** + * {@inheritDoc} + *

+ * The default path {@link DEFAULT_PUSH_PATH} can be changed by using init + * parameter {@link Constants.SERVLET_PARAMETER_PUSH_PATH}. + */ + @Override + public String getPushPath() { + return getApplicationOrSystemProperty( + Constants.SERVLET_PARAMETER_PUSH_PATH, DEFAULT_PUSH_PATH); + } + /** * Log a warning if Vaadin is not running in production mode. */ diff --git a/server/src/com/vaadin/server/DeploymentConfiguration.java b/server/src/com/vaadin/server/DeploymentConfiguration.java index 968ec7c0c3..06556e28a7 100644 --- a/server/src/com/vaadin/server/DeploymentConfiguration.java +++ b/server/src/com/vaadin/server/DeploymentConfiguration.java @@ -195,7 +195,7 @@ public interface DeploymentConfiguration extends Serializable { * * @since 7.4 * - * @return UI class name + * @return the name of the widgetset */ public String getWidgetset(String defaultValue); @@ -213,6 +213,14 @@ public interface DeploymentConfiguration extends Serializable { */ public String getClassLoaderName(); + /** + * Returns the push path configuration option value. Should never be null. + * + * @since 7.4.1 + * @return the path used with server push + */ + public String getPushPath(); + /** * Returns to legacy Property.toString() mode used. See * {@link AbstractProperty#isLegacyToStringEnabled()} for more information. diff --git a/server/src/com/vaadin/server/ServletPortletHelper.java b/server/src/com/vaadin/server/ServletPortletHelper.java index 197d9fe416..1f0c7f02b9 100644 --- a/server/src/com/vaadin/server/ServletPortletHelper.java +++ b/server/src/com/vaadin/server/ServletPortletHelper.java @@ -124,7 +124,8 @@ public class ServletPortletHelper implements Serializable { } public static boolean isPushRequest(VaadinRequest request) { - return hasPathPrefix(request, ApplicationConstants.PUSH_PATH + '/'); + return hasPathPrefix(request, request.getService() + .getDeploymentConfiguration().getPushPath() + '/'); } public static void initDefaultUIProvider(VaadinSession session, diff --git a/server/src/com/vaadin/server/communication/UIInitHandler.java b/server/src/com/vaadin/server/communication/UIInitHandler.java index 3a6dc1e55f..02b4e64159 100644 --- a/server/src/com/vaadin/server/communication/UIInitHandler.java +++ b/server/src/com/vaadin/server/communication/UIInitHandler.java @@ -198,10 +198,11 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { PushMode pushMode = provider.getPushMode(event); if (pushMode == null) { - pushMode = session.getService().getDeploymentConfiguration() - .getPushMode(); + pushMode = session.getConfiguration().getPushMode(); } ui.getPushConfiguration().setPushMode(pushMode); + ui.getPushConfiguration().setPushPath( + session.getConfiguration().getPushPath()); Transport transport = provider.getPushTransport(event); if (transport != null) { diff --git a/server/src/com/vaadin/ui/PushConfiguration.java b/server/src/com/vaadin/ui/PushConfiguration.java index 90ad28542c..d5e89b4b14 100644 --- a/server/src/com/vaadin/ui/PushConfiguration.java +++ b/server/src/com/vaadin/ui/PushConfiguration.java @@ -104,6 +104,26 @@ public interface PushConfiguration extends Serializable { */ public void setFallbackTransport(Transport fallbackTransport); + /** + * Sets the path that is used with push. + * + * @since 7.4.1 + * @param pushPath + * The path to be used with push + * + * @throws IllegalArgumentException + * if the argument is null or empty. + */ + public void setPushPath(String pushPath); + + /** + * Returns the path used with push. + * + * @since 7.4.1 + * @return The path that is used with push + */ + public String getPushPath(); + /** * Returns the given parameter, if set. *

@@ -255,6 +275,32 @@ class PushConfigurationImpl implements PushConfiguration { fallbackTransport.getIdentifier()); } + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.PushConfiguration#setPushPath(java.lang.String) + */ + @Override + public void setPushPath(String pushPath) { + if (pushPath != null && !pushPath.isEmpty()) { + getState().pushPath = pushPath; + } else { + throw new IllegalArgumentException( + "Push path can't be empty or null"); + } + + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.PushConfiguration#getPushPath() + */ + @Override + public String getPushPath() { + return getState(false).pushPath; + } + /* * (non-Javadoc) * @@ -290,5 +336,4 @@ class PushConfigurationImpl implements PushConfiguration { return Collections.unmodifiableCollection(getState(false).parameters .keySet()); } - } diff --git a/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java b/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java index 0518bea650..ccdbfea150 100644 --- a/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java +++ b/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java @@ -158,5 +158,9 @@ public class AbstractDeploymentConfigurationTest { return DefaultDeploymentConfiguration.DEFAULT_SEND_URLS_AS_PARAMETERS; } + @Override + public String getPushPath() { + return null; + } } } diff --git a/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java b/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java index ddee23a9ec..175dcb2b94 100644 --- a/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java +++ b/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java @@ -22,6 +22,7 @@ public class MockDeploymentConfiguration extends private LegacyProperyToStringMode legacyPropertyToStringMode = LegacyProperyToStringMode.DISABLED; private boolean syncIdCheckEnabled = true; private boolean sendUrlsAsParameters = true; + private String pushPath = "PUSH"; @Override public boolean isProductionMode() { @@ -125,4 +126,9 @@ public class MockDeploymentConfiguration extends return sendUrlsAsParameters; } + @Override + public String getPushPath() { + return pushPath; + } + } diff --git a/shared/src/com/vaadin/shared/ApplicationConstants.java b/shared/src/com/vaadin/shared/ApplicationConstants.java index d7aaee6267..990564a6b8 100644 --- a/shared/src/com/vaadin/shared/ApplicationConstants.java +++ b/shared/src/com/vaadin/shared/ApplicationConstants.java @@ -28,8 +28,6 @@ public class ApplicationConstants implements Serializable { public static final String HEARTBEAT_PATH = "HEARTBEAT"; - public static final String PUSH_PATH = "PUSH"; - public static final String PUBLISHED_FILE_PATH = APP_PATH + '/' + "PUBLISHED"; @@ -76,7 +74,7 @@ public class ApplicationConstants implements Serializable { /** * The name of the javascript containing the bootstrap code. The file is * located in the VAADIN directory. - * + * * @since 7.3 */ public static final String VAADIN_BOOTSTRAP_JS = "vaadinBootstrap.js"; @@ -90,7 +88,7 @@ public class ApplicationConstants implements Serializable { /** * The name of the debug version of the javascript containing push support. * The file is located in the VAADIN directory. - * + * * @since 7.1.6 */ public static final String VAADIN_PUSH_DEBUG_JS = "vaadinPush.debug.js"; @@ -102,14 +100,14 @@ public class ApplicationConstants implements Serializable { /** * The name of the parameter used to transmit RPC invocations - * + * * @since 7.2 */ public static final String RPC_INVOCATIONS = "rpc"; /** * The name of the parameter used to transmit the CSRF token - * + * * @since 7.2 */ public static final String CSRF_TOKEN = "csrfToken"; @@ -118,7 +116,7 @@ public class ApplicationConstants implements Serializable { * The name of the parameter used to transmit the sync id. The value can be * set to -1 e.g. when testing with pre-recorded requests to make the * framework ignore the sync id. - * + * * @see com.vaadin.ui.ConnectorTracker#getCurrentSyncId() * @since 7.2 */ diff --git a/shared/src/com/vaadin/shared/ui/ui/UIState.java b/shared/src/com/vaadin/shared/ui/ui/UIState.java index 2f51fef6ee..04e182c5d4 100644 --- a/shared/src/com/vaadin/shared/ui/ui/UIState.java +++ b/shared/src/com/vaadin/shared/ui/ui/UIState.java @@ -110,6 +110,7 @@ public class UIState extends TabIndexState { public static final String FALLBACK_TRANSPORT_PARAM = "fallbackTransport"; public PushMode mode = PushMode.DISABLED; + public String pushPath; public Map parameters = new HashMap(); { parameters diff --git a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java index e2b93ab7d2..5c2e58d3a2 100644 --- a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java +++ b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java @@ -402,9 +402,12 @@ public class ApplicationRunnerServlet extends LegacyVaadinServlet { try { VaadinServletService service = (VaadinServletService) VaadinService .getCurrent(); - session = service - .findVaadinSession(new VaadinServletRequest( - currentRequest, service)); + if (service != null) { + session = service + .findVaadinSession(new VaadinServletRequest( + currentRequest, service)); + } + } finally { /* * Clear some state set by findVaadinSession to diff --git a/uitest/src/com/vaadin/tests/push/PushPath.java b/uitest/src/com/vaadin/tests/push/PushPath.java new file mode 100644 index 0000000000..20771bd84f --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushPath.java @@ -0,0 +1,77 @@ +/* + * 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.tests.push; + +import com.vaadin.annotations.Push; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.ui.Transport; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Label; + +@Push(transport = Transport.WEBSOCKET) +public class PushPath extends AbstractTestUI { + + public static final String PUSH_PATH_LABEL_ID = "push-path-label-id"; + public static final String PUSH_PATH_LABEL_TEXT = "Label by push"; + + @Override + protected void setup(VaadinRequest request) { + // use only websockets + getPushConfiguration().setFallbackTransport(Transport.WEBSOCKET); + + String pushPath = request.getService().getDeploymentConfiguration() + .getPushPath(); + String transport = getPushConfiguration().getTransport().name(); + Label pushPathLabel = new Label(String.format( + "Waiting for push from path '%s' using %s in 3 seconds.", + pushPath, transport)); + addComponent(pushPathLabel); + + new PushThread().start(); + } + + public class PushThread extends Thread { + + @Override + public void run() { + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + } + access(new Runnable() { + + @Override + public void run() { + Label pushLabel = new Label(PUSH_PATH_LABEL_TEXT); + pushLabel.setId(PUSH_PATH_LABEL_ID); + addComponent(pushLabel); + } + }); + + } + } + + @Override + public Integer getTicketNumber() { + return 14432; + } + + @Override + public String getDescription() { + return "Push path should be configurable since some servers can't serve both websockets and long polling from same URL."; + } + +} diff --git a/uitest/src/com/vaadin/tests/push/PushPathTest.java b/uitest/src/com/vaadin/tests/push/PushPathTest.java new file mode 100644 index 0000000000..6357c281f6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushPathTest.java @@ -0,0 +1,41 @@ +/* + * 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.tests.push; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.tests.tb3.WebsocketTest; + +public class PushPathTest extends WebsocketTest { + + private static final int TEN_SECONDS_IN_MS = 10 * 1000; + + @Test + public void testCustomPushPath() throws InterruptedException { + openTestURL(); + sleep(TEN_SECONDS_IN_MS); + Assert.assertEquals(vaadinElementById(PushPath.PUSH_PATH_LABEL_ID) + .getText(), PushPath.PUSH_PATH_LABEL_TEXT); + } + + @Override + public String getDeploymentPath() { + Class uiClass = getUIClass(); + return "/run-pushpath/" + uiClass.getCanonicalName(); + } + +} -- 2.39.5