Deploying to Production

This article explains how to deploy a Vaadin Flow application on Jetty.

Jetty is an open-source project providing an HTTP server, HTTP client, and javax.servlet container.

Applications can be deployed to Jetty servers in 2 different ways:

  1. Embedded Jetty

    • (Using the Jetty Maven Plugin, only during development)

    • Starting the Jetty server Programmatically

  2. Standalone Jetty

    • Deploy web applications as a WAR package

    • Deploy web applications as an exploded directory

    • Deploy web applications using a Context File

Embedded Jetty

Using Jetty has the advantage that it can be instantiated and used in a standard Java program, meaning that it does not need to be separately installed on the server.

“Don’t deploy your application in Jetty, deploy Jetty in your application!” by Jetty.

Running Jetty programmatically requires some manual configuration to make it work with Vaadin.

  1. public final class ManualJetty {
  2. public static void main(String[] args) throws Exception {
  3. Server server = new Server(8080);
  4. // Specifies the order in which the configurations are scanned
  5. Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(server);
  6. classlist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration", "org.eclipse.jetty.plus.webapp.EnvConfiguration", "org.eclipse.jetty.plus.webapp.PlusConfiguration");
  7. classlist.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration", "org.eclipse.jetty.annotations.AnnotationConfiguration");
  8. // Creation of a temporal directory
  9. File tempDir = new File(System.getProperty("java.io.tmpdir"), "JettyTest");
  10. if (tempDir.exists()) {
  11. if (!tempDir.isDirectory()) {
  12. throw new RuntimeException("Not a directory: " + tempDir);
  13. }
  14. } else if (!tempDir.mkdirs()) {
  15. throw new RuntimeException("Could not make: " + tempDir);
  16. }
  17. WebAppContext context = new WebAppContext();
  18. context.setInitParameter("productionMode", "true");
  19. // Context path of the application
  20. context.setContextPath("");
  21. // Exploded WAR or not
  22. context.setExtractWAR(false);
  23. context.setTempDirectory(tempDir);
  24. // It pulls the respective config from the VaadinServlet
  25. context.addServlet(VaadinServlet.class, "/*");
  26. context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*");
  27. context.setParentLoaderPriority(true);
  28. server.setHandler(context);
  29. // This add jars to the jetty classpath in a certain syntax and the pattern makes sure to load all of them
  30. List<Resource> resourceList = new ArrayList<>();
  31. for (String entry : ClassPathHelper.getAllClassPathEntries()) {
  32. File file = new File(entry);
  33. if (entry.endsWith(".jar")) {
  34. resourceList.add(Resource.newResource("jar:" + file.toURI().toURL() + "!/"));
  35. } else {
  36. resourceList.add(Resource.newResource(entry));
  37. }
  38. }
  39. // It adds the web application resources. Styles, client-side components, ...
  40. resourceList.add(Resource.newResource("./src/main/webapp"));
  41. // The base resource is where jetty serves its static content from
  42. context.setBaseResource(new ResourceCollection(resourceList.toArray(new Resource[0])));
  43. server.start();
  44. server.join();
  45. }
  46. }

This programmatic configuration requires some extra dependencies in pom.xml:

  1. <dependency>
  2. <groupId>org.eclipse.jetty</groupId>
  3. <artifactId>jetty-project</artifactId>
  4. <version>${project.version}</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.eclipse.jetty</groupId>
  8. <artifactId>jetty-webapp</artifactId>
  9. <version>${jetty.version}</version>
  10. </dependency>
Note
Depending of Jetty’s configuration, it could require additional dependencies, such as: jetty-annotations,jetty-continuation,javax-websocket-server-impl, …​ For more information about jetty, please consult Jetty Documentation.

Standalone Jetty

Deploying to a standalone Jetty server can be done either by using a WAR file or an exploded directory with the application in it.

It is possible to change the name of the WAR file and exploded directory specifying the finalName in pom.xml:

  1. <build>
  2. <finalName>application</finalName>
  3. ...
  4. </build>

Deploying by Copying WAR

The easiest way to deploy a web application on a Jetty server is probably by copying the WAR file into the webapps directory of Jetty.

The WAR file can be generated executing the following Maven goal:

  1. mvn package -Pproduction

After copying the WAR file into the webapps directory, you can start Jetty by navigating to Jetty’s folder and running the following command:

  1. java -jar start.jar

Deploying by Copying Exploded Directory

An exploded directory is a folder containing the unzipped (exploded) contents and all the application files. It is actually an extracted WAR file (as WAR files are ZIP files).

The command mvn package creates the exploded directory before creating the WAR file, and can be used here as well.

Note
The WAR file and the exploded directory can be found with the same name in the target directory.

Deploying Using Context File

Jetty web server offers the possibility of deploying a web archive located anywhere in the file system by creating a context file for it.

  1. <?xml version="1.0" encoding="ISO-8859-1"?>
  2. <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
  3. "http://www.eclipse.org/jetty/configure.dtd">
  4. <Configure class="org.eclipse.jetty.webapp.WebAppContext">
  5. <Set name="contextPath">/jetty</Set>
  6. <Set name="war">absolute/path/to/jetty-app.war</Set>
  7. </Configure>

Spring Boot

If your Vaadin application is using Spring Boot, it requires an additional configuration for several aspects of the application.

One example of this is urlMapping:

  1. vaadin.urlMapping=/my_mapping/*

An additional Servlet is required to handle the frontend resources for non-root servlets, such as /my_mapping/*. The servlet can be defined in your application class, see here for an example.

For more information about Spring configuration, please consult the Vaadin Spring configuration guide.

Updated 2021-03-09 Edit this article