Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specify custom theme version to solve browser cache issues #11242

Open
Emmenemoi opened this issue Oct 12, 2018 · 3 comments
Open

Allow specify custom theme version to solve browser cache issues #11242

Emmenemoi opened this issue Oct 12, 2018 · 3 comments

Comments

@Emmenemoi
Copy link

When modifying custom themes between app releases, browser cache prevent loading the latest version which could mess a lot the vaadin app.
Same thing for widgetset generated JS if the app embed modified custom widgets.
To solve this we should be able to programmatically setup application version and/or theme version so that vaadinBootstrap.js tells the browser to download the latest versions.

For example for theme:
You could replace line 233 in vaadinBootstrap.js:

loadTheme(themeUri, versionInfo && versionInfo['vaadinVersion']);

with

if (versionInfo && versionInfo['themeVersion'])
    loadTheme(themeUri, versionInfo['themeVersion']);
else
    loadTheme(themeUri, versionInfo && versionInfo['vaadinVersion']);

And allow to programmatically set themeVersion somewhere (SystemVersionsProvider like SystemMessagesProvider ?)

For widgetset we could use applicationVersion within versionInfo object.

@Emmenemoi
Copy link
Author

Full modifications needed:

  • replace line 233 in vaadinBootstrap.js:
               var themeVersion = versionInfo && versionInfo['vaadinVersion'];
                if (versionInfo && versionInfo['appVersion']) {
                	themeVersion = versionInfo['appVersion'];
                }
                loadTheme(themeUri, themeVersion);
  • add in the UIState an appVersion ou themeVersion property and setup the value:
            String appVersion = getClass().getPackage().getImplementationVersion();
            if (state.appVersion == null) {
                Properties prop = new Properties();
                try {
                    prop.load(VaadinServlet.getCurrent().getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF"));
                    state.appVersion = prop.getProperty("Implementation-Version");
                } catch (IOException e) {
                    LoggerFactory.getLogger(UIState.class).error(e.toString());
                }
            }
  • in DeploymentConfiguration add method:

String getAppVersion();

  • in DefaultDeploymentConfiguration, setup version:
@Override
    public String getAppVersion() {
        if (appVersion == null) {
            appVersion = getClass().getPackage().getImplementationVersion();
            if (appVersion == null) {
                Properties prop = new Properties();
                try {
                    prop.load(VaadinServlet.getCurrent().getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF"));
                    appVersion = prop.getProperty("Implementation-Version");
                } catch (IOException e) {
                    getLogger().warning(e.toString());
                }
            }
            // fallback to empty version
            if (appVersion == null) {
                appVersion = "";
            }
        }
        return appVersion;
    }
  • add in UI constructor:
    getState().appVersion = getSession().getService().getDeploymentConfiguration().getAppVersion();
  • in BootstrapHanndler:
           String appVersion = context.getSession().getService().getDeploymentConfiguration().getAppVersion();
        if (appVersion != null && !appVersion.isEmpty()) {
            versionInfo.put("appVersion", appVersion);
        }

@Emmenemoi
Copy link
Author

Emmenemoi commented Aug 13, 2019

Patch file against 8.8:

diff --git a/client/src/main/java/com/vaadin/client/ui/ui/UIConnector.java b/client/src/main/java/com/vaadin/client/ui/ui/UIConnector.java
index 5630cfab3c..eece929560 100644
--- a/client/src/main/java/com/vaadin/client/ui/ui/UIConnector.java
+++ b/client/src/main/java/com/vaadin/client/ui/ui/UIConnector.java
@@ -1163,7 +1163,11 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
                .translateVaadinUri(ApplicationConstants.VAADIN_PROTOCOL_PREFIX
                        + "themes/" + theme + "/styles" + ".css");
        // Parameter appended to bypass caches after version upgrade.
-        themeUrl += "?v=" + Version.getFullVersion();
+        String version = Version.getFullVersion();
+        if (getState().appVersion != null && !getState().appVersion.isEmpty()) {
+            version = getState().appVersion;
+        }
+        themeUrl += "?v=" + version;
        return themeUrl;

    }
diff --git a/server/src/main/java/com/vaadin/server/BootstrapHandler.java b/server/src/main/java/com/vaadin/server/BootstrapHandler.java
index 8f52b67085..351dd961a4 100644
--- a/server/src/main/java/com/vaadin/server/BootstrapHandler.java
+++ b/server/src/main/java/com/vaadin/server/BootstrapHandler.java
@@ -781,6 +781,11 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler {
            versionInfo.put("atmosphereVersion", atmosphereVersion);
        }

+        String appVersion = context.getSession().getService().getDeploymentConfiguration().getAppVersion();
+        if (appVersion != null && !appVersion.isEmpty()) {
+            versionInfo.put("appVersion", appVersion);
+        }
+
        appConfig.put("versionInfo", versionInfo);

        WidgetsetInfo widgetsetInfo = context.getWidgetsetInfo();
diff --git a/server/src/main/java/com/vaadin/server/DefaultDeploymentConfiguration.java b/server/src/main/java/com/vaadin/server/DefaultDeploymentConfiguration.java
index 20cb001e5c..8a8145af54 100644
--- a/server/src/main/java/com/vaadin/server/DefaultDeploymentConfiguration.java
+++ b/server/src/main/java/com/vaadin/server/DefaultDeploymentConfiguration.java
@@ -16,11 +16,13 @@

package com.vaadin.server;

+import java.io.Exception;
import java.util.Locale;
import java.util.Properties;
import java.util.logging.Logger;

import com.vaadin.shared.communication.PushMode;
+import com.vaadin.shared.ui.ui.UIState;

/**
 * The default implementation of {@link DeploymentConfiguration} based on a base
@@ -65,6 +67,7 @@ public class DefaultDeploymentConfiguration
    private final Class<?> systemPropertyBaseClass;
    private boolean syncIdCheck;
    private boolean sendUrlsAsParameters;
+    private String appVersion;

    /**
     * Create a new deployment configuration instance.
@@ -263,6 +266,27 @@ public class DefaultDeploymentConfiguration
        return initParameters;
    }

+    @Override
+    public String getAppVersion() {
+        if (appVersion == null) {
+            appVersion = getClass().getPackage().getImplementationVersion();
+            if (appVersion == null) {
+                Properties prop = new Properties();
+                try {
+                    prop.load(VaadinServlet.getCurrent().getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF"));
+                    appVersion = prop.getProperty("Implementation-Version");
+                } catch (Exception e) {
+                    getLogger().warning(e.toString());
+                }
+            }
+            // fallback to empty version
+            if (appVersion == null) {
+                appVersion = "";
+            }
+        }
+        return appVersion;
+    }
+
    /**
     * Log a warning if Vaadin is not running in production mode.
     */
diff --git a/server/src/main/java/com/vaadin/server/DeploymentConfiguration.java b/server/src/main/java/com/vaadin/server/DeploymentConfiguration.java
index e0700742ef..1dcaaea4e6 100644
--- a/server/src/main/java/com/vaadin/server/DeploymentConfiguration.java
+++ b/server/src/main/java/com/vaadin/server/DeploymentConfiguration.java
@@ -173,4 +173,10 @@ public interface DeploymentConfiguration extends Serializable {
     */
    public String getClassLoaderName();

+    /**
+     * Gets the Vaadin app version.
+     *
+     * @since 8.8
+     */
+    public String getAppVersion();
}

diff --git a/server/src/main/java/com/vaadin/ui/UI.java b/server/src/main/java/com/vaadin/ui/UI.java
index 2a3b913e16..be04c530cd 100644
--- a/server/src/main/java/com/vaadin/ui/UI.java
+++ b/server/src/main/java/com/vaadin/ui/UI.java
@@ -22,14 +22,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.Future;
import java.util.logging.Level;
@@ -328,6 +321,7 @@ public abstract class UI extends AbstractSingleComponentContainer
        registerRpc(windowOrderRpc);
        setSizeFull();
        setContent(content);
+        getState().appVersion = getSession().getService().getDeploymentConfiguration().getAppVersion();
    }


diff --git a/server/src/main/resources/VAADIN/vaadinBootstrap.js b/server/src/main/resources/VAADIN/vaadinBootstrap.js
index a6830f434b..93b53d9e4d 100644
--- a/server/src/main/resources/VAADIN/vaadinBootstrap.js
+++ b/server/src/main/resources/VAADIN/vaadinBootstrap.js
@@ -230,7 +230,11 @@
                var versionInfo = getConfig('versionInfo');

                var themeUri = vaadinDir + 'themes/' + getConfig('theme');
-                loadTheme(themeUri, versionInfo && versionInfo['vaadinVersion']);
+                var themeVersion = versionInfo && versionInfo['vaadinVersion'];
+                if (versionInfo && versionInfo['appVersion']) {
+                	themeVersion = versionInfo['appVersion'];
+                }
+                loadTheme(themeUri, themeVersion);

                var widgetset = getConfig('widgetset');
                var widgetsetUrl = getConfig('widgetsetUrl');
diff --git a/shared/src/main/java/com/vaadin/shared/ui/ui/UIState.java b/shared/src/main/java/com/vaadin/shared/ui/ui/UIState.java
index 90269a8b09..c784e732da 100644
--- a/shared/src/main/java/com/vaadin/shared/ui/ui/UIState.java
+++ b/shared/src/main/java/com/vaadin/shared/ui/ui/UIState.java
@@ -79,6 +79,14 @@ public class UIState extends AbstractSingleComponentContainerState {
     * @since 7.3
     */
    public String theme;
+
+    /**
+     * Used for cache detection
+     *
+     * @since 8.5
+     */
+    public String appVersion;
+
    public ReconnectDialogConfigurationState reconnectDialogConfiguration = new ReconnectDialogConfigurationState();
    {
        primaryStyleName = "v-ui";

@Emmenemoi
Copy link
Author

up. This is very annoying for the users: they must manually clear the cache.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants