Docs

Documentation versions (currently viewingVaadin 25 (prerelease))

Single-Module Projects

How and when to use single-module projects for Vaadin applications.

A single-module project consists of a single directory, with a single POM file and a single source directory. During the build, Maven packages the module either into a self-contained executable JAR file, or into a WAR file.

Single-module projects are simple and easy to understand. They’re best suited for smaller applications, and ones that are maintained by small development teams. They’re also suitable for new projects, since it’s easy to migrate from a single-module project to a multi-module one — if the need arises.

Note
Your architecture imposes constraints on how parts of your code can interact. In a single-module project, all of the code is in the same place. There are no technical safeguards to prevent breaking these constraints — intentionally or otherwise. The risk of this happening grows with the codebase or as the number of people involved increases. This can lead to the code becoming unmaintainable: known as a "Big Ball of Mud". When it seems this may be approaching, consider adding ArchUnit tests to your project, or converting to a multi-module project.

You can use various starters to create new single-module Vaadin projects (see Getting Started). Or you can create a new project without starters, by using a basic Maven POM file and adding the necessary sections to it.

Spring Boot Starter Parent

For all Spring Boot projects, much of the configuration is imported through the spring-boot-starter-parent:

Source code
XML
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>4.0.0-M1</version> 1
    <relativePath/>
</parent>
  1. You can check for the latest version on the MVN Repository.

The parent imports all of the Spring Boot dependencies and configures the most common Maven plugins (e.g., the compiler) using sensible defaults.

Project Properties

Declare all other dependency versions as project properties, like this:

Source code
XML
<properties>
    <java.version>21</java.version> 1
    <vaadin.version>24.8.3</vaadin.version> 2
</properties>
  1. This property is used by spring-boot-starter-parent to configure the Java compiler plugin.

  2. You can check for the latest version on the MVN Repository.

Declaring the dependency versions as properties makes it easier to upgrade. It also helps to get an overview of which dependencies your application has — other than the Spring Boot dependencies.

Vaadin Dependencies

Like Spring Boot, Vaadin comes with its own set of dependencies. These are imported through a Bill of Materials (BOM) like this:

Source code
XML
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-bom</artifactId>
            <version>${vaadin.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Importing the BOM makes the dependencies known to your project. When you use them, you don’t have to declare their versions. To use the dependencies, add them to your project like so:

Source code
XML
<dependencies>
    <dependency>
        <groupId>com.vaadin</groupId>
        <artifactId>vaadin-spring-boot-starter</artifactId>
    </dependency>
</dependencies>

The only dependency you need for building a simple Vaadin application is vaadin-spring-boot-starter. In a real application, you would also add dependencies for at least persistence and database access — and for running tests.

Maven Plugins

Next, to build your project, you’ll need to add two more Maven plugins:

Source code
XML
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>

        <plugin>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-maven-plugin</artifactId>
            <version>${vaadin.version}</version>
            <executions>
                <execution>
                    <goals>
                        <goal>prepare-frontend</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

The spring-boot-maven-plugin does plenty, but for now think of it as the plugin that packages a project into a single, executable JAR file. For more information about this plugin, see the Spring Boot documentation.

The vaadin-maven-plugin also does plenty. The prepare-frontend goal checks that you have sufficiently recent versions of the node and npm tools. It installs them if they’re missing. It also reviews all of the resources used by the application, generates some missing source files, and moves them into the correct locations.

Depending on how much the plugin has to do, the first execution of this goal may take some time. However, later executions are often fast. Therefore, include this goal in every build. For more information, see Production Build and Maven Configuration Properties.

After you’ve executed prepare-frontend, you’re ready to run your application in development mode.

Production Build Profile

To make a production build, you also have to run the build-frontend goal. This goal takes much longer to complete, which is why it’s often configured inside its own production Maven profile:

Source code
XML
<profiles>
    <profile>
        <id>production</id>
        <dependencies>
            <dependency>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-core</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>com.vaadin</groupId>
                        <artifactId>vaadin-dev</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>com.vaadin</groupId>
                    <artifactId>vaadin-maven-plugin</artifactId>
                    <version>${vaadin.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>build-frontend</goal>
                            </goals>
                            <phase>compile</phase>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

With this, the build-frontend goal runs only when the production profile is active. This profile also excludes the vaadin-dev dependency. It’s only needed in development.

The Complete POM

A fully configured POM file for a single-module Vaadin application looks like this:

Source code
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example.application</groupId>
    <artifactId>application</artifactId>
    <name>application</name>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>4.0.0-M1</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>21</java.version>
        <vaadin.version>24.8.3</vaadin.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-bom</artifactId>
                <version>${vaadin.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-maven-plugin</artifactId>
                <version>${vaadin.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>prepare-frontend</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>production</id>
            <dependencies>
                <dependency>
                    <groupId>com.vaadin</groupId>
                    <artifactId>vaadin-core</artifactId>
                    <exclusions>
                        <exclusion>
                            <groupId>com.vaadin</groupId>
                            <artifactId>vaadin-dev</artifactId>
                        </exclusion>
                    </exclusions>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <groupId>com.vaadin</groupId>
                        <artifactId>vaadin-maven-plugin</artifactId>
                        <version>${vaadin.version}</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>build-frontend</goal>
                                </goals>
                                <phase>compile</phase>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>