Project and first server
Javalin has no project generator: it is a single library, and the project is an ordinary Maven project with a few dependencies. We create it by hand: folders, a pom.xml file and a Main class. It takes a couple of minutes, and the project contains nothing extra.
Project folders
Create a blog folder with this structure:
blog/
├── pom.xml
└── src/
└── main/
└── java/com/example/blog/
└── Main.java
Later we add src/main/resources for files and src/test/java for tests.
pom.xml
The pom.xml file lives in the root of the blog folder:
<!-- pom.xml -->
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>blog</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.release>25</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<javalin.version>7.2.3</javalin.version>
</properties>
<dependencies>
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>
<version>${javalin.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.18</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.22.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.14.1</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.6.4</version>
<configuration>
<mainClass>com.example.blog.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>| Dependency | Why |
|---|---|
javalin | The framework itself and the embedded Jetty |
slf4j-simple | Prints logs to the console |
jackson-databind | Turns objects into JSON and back |
The exec-maven-plugin plugin runs the Main class with a Maven command.
The first server
Create the Main.java file:
// src/main/java/com/example/blog/Main.java
package com.example.blog;
import io.javalin.Javalin;
public class Main {
public static void main(String[] args) {
Javalin app = Javalin.create(config -> {
config.routes.get("/", ctx -> ctx.result("Hello, Javalin!"));
});
app.start(8080);
}
}Javalin.create takes a lambda with the configuration. Inside it, config.routes.get declares a route: answer GET / with a string. The start(8080) method starts the server on port 8080.
Running
In the blog folder run:
mvn compile exec:javaMaven downloads the dependencies, compiles the code and starts the server. The end of the log (shortened):
[com.example.blog.Main.main()] INFO io.javalin.Javalin - Starting Javalin ...
[com.example.blog.Main.main()] INFO org.eclipse.jetty.server.Server - jetty-12.1.12; ...
[com.example.blog.Main.main()] INFO io.javalin.Javalin - Javalin started in 573ms \o/
[com.example.blog.Main.main()] INFO io.javalin.Javalin - Listening on http://localhost:8080/
[com.example.blog.Main.main()] INFO io.javalin.Javalin - You are running Javalin 7.2.3 (released August 11, 2026).
Open http://localhost:8080 in a browser or call the server from a second terminal:
curl http://localhost:8080Hello, Javalin!
The server runs until you press Ctrl+C. After every code change, stop it and run the command again.
Common mistake
If you forget the slf4j-simple dependency, the server starts but prints no logs, and at the beginning of the output Javalin prints a hint:
#########################################################################
Javalin: It looks like you don't have a logger in your project.
The easiest way to fix this is to add 'slf4j-simple':
...
#########################################################################
SLF4J(W): No SLF4J providers were found.
SLF4J(W): Defaulting to no-operation (NOP) logger implementation
Without logs you see neither the server address nor errors in handlers. Add the dependency from the table above.