Skip to content

Commit 349cc11

Browse files
authored
feat: Caching for Spring Boot DevTools reload (#17621)
Adds some cached data for use in case of Spring Boot DevTools reload. CustomResourceLoader: added a few packages to default never-scan list DevModeServletContextListener: Dynamically generates a white list for dev mode package scanner RouteServletContextListener: Dynamically generates a white list for route package scanner LookupInitializerListener: Cache found classes VaadinAppShellContextListener: Cache found classes CustomResourceLoader: Cache valid/skipped status of resources for later use Also adds a configuration property (vaadin.devmode-caching) for toggling the feature. Fixes #17487
1 parent daecc25 commit 349cc11

File tree

20 files changed

+951
-86
lines changed

20 files changed

+951
-86
lines changed

flow-tests/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@
292292
<module>test-live-reload-multimodule/pom-devbundle.xml</module>
293293
<module>test-theme-editor</module>
294294
<module>test-redeployment</module>
295+
<module>test-redeployment-no-cache</module>
295296

296297
<module>test-scalability</module>
297298
<module>test-servlet</module>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<artifactId>flow-tests</artifactId>
6+
<groupId>com.vaadin</groupId>
7+
<version>24.2-SNAPSHOT</version>
8+
</parent>
9+
<artifactId>flow-test-redeployment-no-cache</artifactId>
10+
<name>Test to ensure dev mode caching is not used when it's disabled</name>
11+
<packaging>jar</packaging>
12+
13+
<properties>
14+
<maven.deploy.skip>true</maven.deploy.skip>
15+
</properties>
16+
17+
<dependencyManagement>
18+
<dependencies>
19+
<dependency>
20+
<groupId>com.fasterxml.jackson</groupId>
21+
<artifactId>jackson-bom</artifactId>
22+
<version>${jackson.version}</version>
23+
<type>pom</type>
24+
<scope>import</scope>
25+
</dependency>
26+
</dependencies>
27+
</dependencyManagement>
28+
29+
<dependencies>
30+
<dependency>
31+
<groupId>com.vaadin</groupId>
32+
<artifactId>flow-test-resources</artifactId>
33+
<version>${project.version}</version>
34+
</dependency>
35+
<dependency>
36+
<groupId>com.vaadin</groupId>
37+
<artifactId>flow-test-common</artifactId>
38+
<version>${project.version}</version>
39+
</dependency>
40+
<dependency>
41+
<groupId>com.vaadin</groupId>
42+
<artifactId>vaadin-dev-server</artifactId>
43+
<version>${project.version}</version>
44+
</dependency>
45+
<dependency>
46+
<groupId>com.vaadin</groupId>
47+
<artifactId>vaadin-spring</artifactId>
48+
<version>${project.version}</version>
49+
</dependency>
50+
<dependency>
51+
<groupId>com.vaadin</groupId>
52+
<artifactId>flow-test-lumo</artifactId>
53+
<version>${project.version}</version>
54+
</dependency>
55+
<dependency>
56+
<groupId>org.springframework.boot</groupId>
57+
<artifactId>spring-boot-starter-web</artifactId>
58+
<version>${spring.boot.version}</version>
59+
<exclusions>
60+
<exclusion>
61+
<groupId>org.springframework.boot</groupId>
62+
<artifactId>spring-boot-starter-logging</artifactId>
63+
</exclusion>
64+
</exclusions>
65+
</dependency>
66+
<dependency>
67+
<groupId>org.springframework.boot</groupId>
68+
<artifactId>spring-boot-devtools</artifactId>
69+
<version>${spring.boot.version}</version>
70+
</dependency>
71+
72+
<dependency>
73+
<groupId>org.apache.commons</groupId>
74+
<artifactId>commons-lang3</artifactId>
75+
<scope>test</scope>
76+
</dependency>
77+
</dependencies>
78+
79+
<build>
80+
<plugins>
81+
<plugin>
82+
<groupId>org.springframework.boot</groupId>
83+
<artifactId>spring-boot-maven-plugin</artifactId>
84+
<version>${spring.boot.version}</version>
85+
<executions>
86+
<execution>
87+
<id>start-server</id>
88+
<phase>pre-integration-test</phase>
89+
<goals>
90+
<goal>start</goal>
91+
</goals>
92+
</execution>
93+
<execution>
94+
<id>stop-server</id>
95+
<phase>post-integration-test</phase>
96+
<goals>
97+
<goal>stop</goal>
98+
</goals>
99+
</execution>
100+
</executions>
101+
</plugin>
102+
<plugin>
103+
<groupId>com.vaadin</groupId>
104+
<artifactId>flow-maven-plugin</artifactId>
105+
</plugin>
106+
</plugins>
107+
</build>
108+
109+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2000-2023 Vaadin Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
17+
package com.vaadin.flow.uitest.ui;
18+
19+
import com.vaadin.flow.component.page.AppShellConfigurator;
20+
import com.vaadin.flow.theme.Theme;
21+
22+
public class AppShell implements AppShellConfigurator {
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2000-2023 Vaadin Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.vaadin.flow.uitest.ui;
17+
18+
import org.springframework.boot.SpringApplication;
19+
import org.springframework.boot.autoconfigure.SpringBootApplication;
20+
21+
@SpringBootApplication
22+
public class Application {
23+
public static void main(String[] args) {
24+
SpringApplication.run(Application.class, args);
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright 2000-2023 Vaadin Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.vaadin.flow.uitest.ui;
17+
18+
import java.lang.reflect.Field;
19+
import java.util.Set;
20+
21+
import com.vaadin.flow.component.html.Div;
22+
import com.vaadin.flow.component.html.Span;
23+
import com.vaadin.flow.router.Route;
24+
25+
@Route(value = "com.vaadin.flow.uitest.ui.DevModeNoClassCacheView")
26+
public class DevModeNoClassCacheView extends Div {
27+
28+
@SuppressWarnings("unchecked")
29+
public DevModeNoClassCacheView() {
30+
31+
try {
32+
Class<?> reloadCacheClass = Class
33+
.forName("com.vaadin.flow.spring.ReloadCache");
34+
35+
// appShellClasses;
36+
Field appShellClassesField = reloadCacheClass
37+
.getDeclaredField("appShellClasses");
38+
appShellClassesField.setAccessible(true);
39+
Set<Class<?>> appShellClasses = (Set<Class<?>>) appShellClassesField
40+
.get(null);
41+
add(new Span(
42+
"appshell class count:" + (appShellClasses == null ? "0"
43+
: appShellClasses.size())));
44+
45+
// lookupClasses;
46+
Field lookupClassesField = reloadCacheClass
47+
.getDeclaredField("lookupClasses");
48+
lookupClassesField.setAccessible(true);
49+
Set<Class<?>> lookupClasses = (Set<Class<?>>) lookupClassesField
50+
.get(null);
51+
add(new Span("lookup class count:"
52+
+ (lookupClasses == null ? "0" : lookupClasses.size())));
53+
54+
// validResources
55+
Field validResourcesField = reloadCacheClass
56+
.getDeclaredField("validResources");
57+
validResourcesField.setAccessible(true);
58+
Set<String> validResources = (Set<String>) validResourcesField
59+
.get(null);
60+
add(new Span("valid resource count:"
61+
+ (validResources == null ? "0" : validResources.size())));
62+
63+
// skippedResources
64+
Field skippedResourcesField = reloadCacheClass
65+
.getDeclaredField("skippedResources");
66+
skippedResourcesField.setAccessible(true);
67+
Set<String> skippedResources = (Set<String>) skippedResourcesField
68+
.get(null);
69+
add(new Span(
70+
"skipped resource count:" + (skippedResources == null ? "0"
71+
: skippedResources.size())));
72+
73+
// dynamicWhiteList;
74+
Field dynamicWhiteListField = reloadCacheClass
75+
.getDeclaredField("dynamicWhiteList");
76+
dynamicWhiteListField.setAccessible(true);
77+
Set<String> dynamicWhiteList = (Set<String>) dynamicWhiteListField
78+
.get(null);
79+
add(new Span("dynamic white list count:"
80+
+ (dynamicWhiteList == null ? "0"
81+
: dynamicWhiteList.size())));
82+
83+
// routePackages;
84+
Field routePackagesField = reloadCacheClass
85+
.getDeclaredField("routePackages");
86+
routePackagesField.setAccessible(true);
87+
Set<String> routePackages = (Set<String>) routePackagesField
88+
.get(null);
89+
Span span = new Span("route packages count:"
90+
+ (routePackages == null ? "0" : routePackages.size()));
91+
span.setId("last-span");
92+
add(span);
93+
94+
} catch (ClassNotFoundException | NoSuchFieldException
95+
| IllegalAccessException e) {
96+
throw new RuntimeException(e);
97+
}
98+
}
99+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
server.port=8888
2+
vaadin.frontend.hotdeploy=true
3+
vaadin.devmode-caching=false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2000-2023 Vaadin Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.vaadin.flow.uitest.ui;
17+
18+
import java.util.List;
19+
20+
import net.jcip.annotations.NotThreadSafe;
21+
import org.junit.Assert;
22+
import org.junit.Test;
23+
import org.openqa.selenium.By;
24+
25+
import com.vaadin.flow.testutil.ChromeBrowserTest;
26+
import com.vaadin.testbench.TestBenchElement;
27+
28+
@NotThreadSafe
29+
public class DevModeNoClassCacheIT extends ChromeBrowserTest {
30+
31+
@Override
32+
protected String getTestPath() {
33+
return super.getTestPath().replace("/view", "");
34+
}
35+
36+
@Test
37+
public void testDevModeClassCacheNotPopulated() {
38+
open();
39+
40+
waitForElementPresent(By.id("last-span"));
41+
42+
List<TestBenchElement> allSpans = $("span").all();
43+
44+
for (int i = 0; i < 6; i++) {
45+
String[] value = allSpans.get(i).getText().split(":");
46+
Assert.assertEquals("Expected " + value[0] + " to be 0.", 0,
47+
Integer.parseInt(value[1]));
48+
}
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2000-2023 Vaadin Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.vaadin.flow.uitest.ui;
17+
18+
import java.util.UUID;
19+
20+
import com.vaadin.flow.component.Text;
21+
import com.vaadin.flow.component.html.Div;
22+
import com.vaadin.flow.component.html.NativeButton;
23+
import com.vaadin.flow.component.html.Span;
24+
25+
public abstract class AbstractReloadView extends Div {
26+
27+
public static final String TRIGGER_RELOAD_ID = "triggerReload";
28+
29+
// This ensures the view is not serializable
30+
private Object preventSerialization = new Object();
31+
32+
public UUID viewId = UUID.randomUUID();
33+
34+
protected void addTriggerButton() {
35+
final NativeButton triggerButton = new NativeButton("Trigger reload",
36+
event -> Application.triggerReload());
37+
triggerButton.setId(TRIGGER_RELOAD_ID);
38+
add(triggerButton);
39+
}
40+
41+
protected void addViewId() {
42+
Div div = new Div();
43+
Span span = new Span(viewId.toString());
44+
span.setId("viewId");
45+
div.add(new Text("The view id is: "), span);
46+
add(div);
47+
}
48+
}

flow-tests/test-redeployment/src/main/java/com/vaadin/flow/uitest/ui/Application.java

+15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
/*
2+
* Copyright 2000-2023 Vaadin Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
116
package com.vaadin.flow.uitest.ui;
217

318
import java.io.File;

0 commit comments

Comments
 (0)