Developing without Server Restarts
Note: HotswapAgent+DCEVM is not supported for the latest Vaadin LTS (Vaadin 14). See the current Development Workflow documentation on the Vaadin Docs site for the recommended hot-deploy solution for your underlying framework (plain servlet, Spring or CDI).
A commonly heard argument against UI development in Java is that it takes time between making changes and seeing the changes in the browser. If you make a Java change which can't be hotswapped, you wait for the server to restart or at least the app to redeploy, then you refresh the browser, log in to the app again, find the correct view and check if your changes were correct. Then you repeat. And repeat.
JRebel offers a commercial solution for Vaadin Framework 7/8, which makes it possible to make almost any kind of Java changes without restarting the server. For Vaadin 10 there is also an open source solution which offers similar features: HotswapAgent+DCEVM with a Vaadin plugin.
HotswapAgent is a project whose "main purpose [...] is to avoid infamous change→restart + wait→check development lifecycle". Together with DCEVM, which is a patch for the JDK, it allows you to make almost any changes to your Java classes without requiring a server restart (everything except "change the superclass or remove an interface" according to the website). To use HotswapAgent you need to install DCEVM, download HotswapAgent and start your server with suitable JVM arguments.
Download a DCEVM compatible with your JDK 8 version
Download it from dcevm.github.io or github.com/dcevm/dcevm/releases. Not all JDK releases are supported and you are probably best off with using Java 8. Run the installer java -jar installer.jar
. To avoid modifying your existing JVM, choose to install it as an "alternative JVM".
There seem to be some builds of DCEVM for Java 9 and 10. The Java 11 version is still in progress at https://github.com/HotswapProjects/openjdk-jdk11. Sticking to 8 for now seems like a safe bet.
Download HotswapAgent
The Vaadin plugin is included in HotswapAgent 1.3.0 and later. Either download the jar file and place it in a suitable directory or add it as a development time dependency to your Maven/Gradle/something project, e.g.
<dependency>
<groupId>org.hotswapagent</groupId>
<artifactId>hotswap-agent</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hotswapagent</groupId>
<artifactId>hotswap-agent</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
Start your server with suitable JVM arguments
The hot swap operation uses the standard JVM debug connection to update classes, so you should run your server inside an IDE in debug mode.
To enable DCEVM, if you installed it as an alternative JVM, you need to pass the -XXaltjvm=dcevm
JVM argument. To enable HotswapAgent you need to pass the -javaagent:/path/to/hotswap.jar
JVM argument.
For example, if you take the Beverage Buddy starter: vaadin.com/start/v10-simple-ui and add the Maven dependency described above, you could start the server as
mvn jetty:run -XXaltjvm=dcevm -javaagent:/your/home/.m2/repository/org/hotswapagent/hotswap-agent/1.3.0/hotswap-agent-1.3.0.jar
mvn jetty:run -XXaltjvm=dcevm -javaagent:/your/home/.m2/repository/org/hotswapagent/hotswap-agent/1.3.0/hotswap-agent-1.3.0.jar
Similarly, for vaadin.com/start/v10-project-base-spring, which is Spring Boot based, you can launch the Application
class using
-XXaltjvm=dcevm -javaagent:/your/home/.m2/repository/org/hotswapagent/hotswap-agent/1.3.0/hotswap-agent-1.3.0.jar
-XXaltjvm=dcevm -javaagent:/your/home/.m2/repository/org/hotswapagent/hotswap-agent/1.3.0/hotswap-agent-1.3.0.jar
Note that you probably do not want to use Spring Devtools if using HotswapAgent to avoid reload conflicts, similarly to how you want to disable redeployment in the server.
How do you know it is working?
Add a new Java class with a @Route
annotation, e.g.
@Route("test")
public class TestView extends Div {
public TestView() {
setText("Blazing Hot");
}
}
@Route("test")
public class TestView extends Div {
public TestView() {
setText("Blazing Hot");
}
}
Open http://localhost:8080/test in your browser and you will see the new view.
Make sure you have disabled any automatic server restarts, such as <scaninterval>
in Jetty or auto-deploy in Tomcat. Otherwise, you will quickly hot deploy changes and then still wait for the server to restart. That's like ordering fast food with overnight shipping.
EDIT: Updated version to stable 1.3.0 and added IntelliJ examples