Docs

Documentation versions (currently viewingVaadin 24)

Meet Your Walking Skeleton

Learn about the building blocks of a Vaadin walking skeleton.

Open your newly generated walking skeleton in your Java IDE. The walking skeleton is a single-module Maven project. For Maven newcomers, see the Maven in 5 Minutes tutorial before proceeding.

The most important files and directories in your skeleton are the following:

my-application/
├── src/
│   ├── main/
│   │   ├── frontend/      (1)
│   │   │   └── ...
│   │   ├── java/          (2)
│   │   │   └── ...
│   │   └── resources/     (3)
│   │   │   └── ...
│   └── test/
│       └── java/          (4)
│           └── ...
└── pom.xml                (5)
  1. Frontend files, such as CSS and TypeScript files.

  2. Java source files.

  3. Configuration files and other files needed by the application.

  4. Java test files.

  5. Maven POM-file for your application.

To make building easier, the skeleton includes the Maven Wrapper. Because of this, you don’t have to install Maven on your computer. Instead, you can use the mvnw (macOS and Linux) or mvnw.cmd (Windows) scripts to run Maven on the command line.

The skeleton includes a .gitignore file optimized for Vaadin projects, and configuration files for the Spotless code formatter. The code formatter is needed when you generate code with Vaadin Copilot, since it does not format the code itself.

The LICENSE.md file is a placeholder for your application’s license. Replace with your own license, or delete if you don’t need it.

Next, you’ll have a closer look at the Java files, the frontend files, and the POM-file.

Java Files

A walking skeleton always contains the following Java files, regardless of whether you chose to generate a Flow view or a Hilla view:

src
├── main/java
│   ├── [application package]
│   │   ├── base                           (1)
│   │   │   └── domain
│   │   │       └── AbstractEntity.java
│   │   └── todo                           (2)
│   │       ├── domain
│   │       │   ├── Todo.java
│   │       │   └── TodoRepository.java
│   │       └── service
│   │           └── TodoService.java
│   └── Application.java                   (3)
└── test/java
    └── [application package]
        ├── todo
        │   └── service
        │       └── TodoServiceIT.java (4)
        └── ArchitectureTest.java          (5)
  1. The base feature package.

  2. The todo feature package.

  3. Main entry point into the application.

  4. Example integration test for the TodoService.

  5. ArchUnit architecture test for the entire application.

If you generated a Flow view, the project contains more Java files. You’ll learn about those later.

The main entry point into the application is Application.java. This class contains the main() method that start up the Spring Boot application.

The skeleton follows a feature-based package structure, organizing code by functional units rather than traditional architectural layers. It includes two feature packages: base and todo.

  • The base package contains classes meant for reuse across different features, either through composition or inheritance.

  • The todo package is an example feature package that demonstrates the structure. It represents a self-contained unit of functionality, including UI components, business logic, and data access. Once you create your own features, you’ll remove this package.

This feature-driven approach keeps related code together, making it easier to maintain, extend, and understand. A feature package could represent anything from a specific use case (e.g., "User Registration"), a UI view (e.g., "Dashboard"), or even a business subdomain (e.g., "Billing"). By grouping everything needed for a feature into a single package structure, you avoid scattering logic across layers and reduce unnecessary coupling.

You’ll find package-info.java files in every package. These files add the @NullMarked annotation from JSpecify to each package. This instructs static analysis tools that every return value and method parameter can never be null unless explicitly stated with a @Nullable annotation. This is a good practice that reduces bugs caused by NullPointerException.

ArchitectureTest.java is an ArchUnit test that guards against unintentional dependencies between classes. As your application grows, it helps keep your code base in shape.

The Todo Feature

The todo feature consists of a JPA entity, a Spring Data JPA repository interface, and an application service.

The repository stores and fetches entities from a relational database. The skeleton uses an in-memory H2 database. This is useful for prototyping, but soon you’ll want to replace it with something else.

The application service acts as the API of the feature and is the boundary between the presentation layer and the application layer. Its main purpose in the skeleton is to show how an application service interacts with the domain model in a Vaadin application.

The todo service has a sample integration test. It starts up the application and its embedded H2 database, and checks that the service works as expected. Its main purpose in the skeleton is to show how to write integration tests for application services.

Java Views Flow

If you generated a Flow view, you’ll find some extra Java files in the skeleton:

src
└── main/java
    └── [application package]
        ├── base
        │   └── ui
        │       ├── component
        │       │   └── ViewToolbar.java
        │       └── view
        │           ├── MainErrorHandler.java
        │           └── MainLayout.java
        └── todo
            └── ui
                └── view
                    └── TodoView.java

The base feature package contains one user interface package with two sub-packages: component and view.

The component package contains custom UI components that can be reused throughout the entire application. The skeleton only contains one, but as your application grows, you’ll add more components to this package.

The view package contains view-related classes that cut across multiple views in multiple features. The skeleton contains an error handler, and a main layout.

The error handler receives all exceptions that reach the user interface, logs them, and shows an error notification to the user. You’ll want to customize this as the application grows.

Your application shows all the views inside the main layout by default. It contains the application’s name, a navigation menu, and a mock user menu that doesn’t do anything. You’ll want to at least change the application name, and either remove or implement the user menu.

The todo feature package contains one UI-related package. It contains the view that allows users to create and list tasks to do.

Frontend Files

A walking skeleton always contains the following frontend files, regardless of whether you chose to generate a Flow view or a Hilla view:

src
└── main/frontend
    └── themes
        └── default
            ├── styles.css
            └── theme.json

This is an empty theme called default, based on the Lumo theme. It is activated in the Application class, using the @Theme annotation.

If you’ve started up your application, you’ll see some auto-generated files in the frontend directory as well. You’ll find an index.html file, and a generated directory. You don’t have to touch these for now.

React Views Hilla

If you generated a Hilla view, you’ll find more frontend files in the skeleton:

src
└── main/frontend
    ├── components
    │   └── ViewToolbar.tsx
    └── views
        ├── @index.tsx
        ├── @layout.tsx
        └── _ErrorHandler.ts

The components directory contains custom UI components that can be reused throughout the entire application. The skeleton only contains one, but as your application grows, you’ll add more components to this directory.

The views directory contains an example view, a main layout, and an error handler. The file names in this directory all have special meaning. You’ll learn about it later.

The example view - @index.tsx - allows users to add and list tasks to do.

Your application shows all the views inside the main layout - @layout.tsx - by default. It contains the application’s name, a navigation menu, and a mock user menu that doesn’t do anything. You’ll want to at least change the application name, and either remove or implement the user menu.

The error handler is a TypeScript function that logs the error to the console and shows a notification to the user. The error handler is not a React error boundary. It is designed to handle errors that occur when calling application services. Because of this, you have to manually catch the errors you want to handle, and call the error handler. The example view shows you how to do this.

The POM File

The POM file is a typical Spring Boot, single-module Maven project file. It uses the spring-boot-starter-parent, so all the Spring Boot dependencies are available for use. It also brings in the Vaadin dependencies, and ArchUnit.

The spring-boot-maven-plugin is used to package the application into a single, executable JAR file.

The spotless-maven-plugin is used to format the Java and TypeScript source files.

The vaadin-maven-plugin is used to prepare and build the frontend files. Under the hood it is using npm and Vite.

The POM file defines two build profiles: production, and integration-test.

The production profile triggers a production build, and is deactivated by default. You’ll learn more about making a production build on the Build a Project page.

The integration-test profile runs integration tests during the verify phase, and is deactivated by default.