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:
Embedded Jetty
(Using the Jetty Maven Plugin, only during development)
Starting the Jetty server Programmatically
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.
public final class ManualJetty {
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
// Specifies the order in which the configurations are scanned
Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(server);
classlist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration", "org.eclipse.jetty.plus.webapp.EnvConfiguration", "org.eclipse.jetty.plus.webapp.PlusConfiguration");
classlist.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration", "org.eclipse.jetty.annotations.AnnotationConfiguration");
// Creation of a temporal directory
File tempDir = new File(System.getProperty("java.io.tmpdir"), "JettyTest");
if (tempDir.exists()) {
if (!tempDir.isDirectory()) {
throw new RuntimeException("Not a directory: " + tempDir);
}
} else if (!tempDir.mkdirs()) {
throw new RuntimeException("Could not make: " + tempDir);
}
WebAppContext context = new WebAppContext();
context.setInitParameter("productionMode", "true");
// Context path of the application
context.setContextPath("");
// Exploded WAR or not
context.setExtractWAR(false);
context.setTempDirectory(tempDir);
// It pulls the respective config from the VaadinServlet
context.addServlet(VaadinServlet.class, "/*");
context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*");
context.setParentLoaderPriority(true);
server.setHandler(context);
// This add jars to the jetty classpath in a certain syntax and the pattern makes sure to load all of them
List<Resource> resourceList = new ArrayList<>();
for (String entry : ClassPathHelper.getAllClassPathEntries()) {
File file = new File(entry);
if (entry.endsWith(".jar")) {
resourceList.add(Resource.newResource("jar:" + file.toURI().toURL() + "!/"));
} else {
resourceList.add(Resource.newResource(entry));
}
}
// It adds the web application resources. Styles, client-side components, ...
resourceList.add(Resource.newResource("./src/main/webapp"));
// The base resource is where jetty serves its static content from
context.setBaseResource(new ResourceCollection(resourceList.toArray(new Resource[0])));
server.start();
server.join();
}
}
This programmatic configuration requires some extra dependencies in pom.xml
:
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${jetty.version}</version>
</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
:
<build>
<finalName>application</finalName>
...
</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:
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:
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.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
"http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/jetty</Set>
<Set name="war">absolute/path/to/jetty-app.war</Set>
</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
:
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.