See the documentation page for up-to-date information.
Introducing Javalin
Javalin is a very lightweight web framework for Kotlin and Java, inspired by Sparkjava and koa.js. Javalin is written in Kotlin with a few functional interfaces written in Java. This was necessary to provide an enjoyable and near identical experience for both Kotlin and Java developers.
Javalin is really more library than framework; you don’t need to extend or implement anything and there are very few “Javalin-concepts” you have to learn. Let’s look at some examples:
Hello World
- Kotlin
- Java
fun main(args: Array<String>) {
val app = Javalin.start(7000)
app.get("/") { ctx -> ctx.result("Hello World") }
}
public static void main(String[] args) {
Javalin app = Javalin.start(7000);
app.get("/", ctx -> ctx.result("Hello World"));
}
API structure and server config
- Kotlin
- Java
val app = Javalin.create().apply {
enableStaticFiles("/public")
enableStandardRequestLogging()
port(port)
}.start()
app.routes {
path("users") {
get(UserController::getAllUserIds)
post(UserController::createUser)
path(":user-id") {
get(UserController::getUser)
patch(UserController::updateUser)
delete(UserController::deleteUser)
}
}
}
Javalin app = Javalin.create()
.enableStaticFiles("/public")
.enableStandardRequestLogging()
.port(port)
.start();
app.routes(() -> {
path("users", () -> {
get(UserController::getAllUserIds);
post(UserController::createUser);
path(":user-id"(() -> {
get(UserController::getUser);
patch(UserController::updateUser);
delete(UserController::deleteUser);
});
});
});
Filters and mappers
- Kotlin
- Java
app.before("/some-path/*") { ctx -> ... } // runs before requests to /some-path/*
app.before { ctx -> ... } // runs before all requests
app.after { ctx -> ... } // runs after all requests
app.exception(Exception.class) { e, ctx -> ... } // runs if uncaught Exception
app.error(404) { ctx -> ... } // runs if status is 404 (after all other handlers)
app.before("/some-path/*", ctx -> { ... }); // runs before requests to /some-path/*
app.before(ctx -> { ... }); // runs before all requests
app.after(ctx -> { ... }); // runs after all requests
app.exception(Exception.class, (e, ctx) -> { ... }); // runs if uncaught Exception
app.error(404, ctx -> { ... }); // runs if status is 404 (after all other handlers)
WebSockets
- Kotlin
- Java
app.ws("/websocket") { ws ->
ws.onConnect { session -> println("Connected") }
ws.onMessage { session, message ->
println("Received: " + message)
session.remote.sendString("Echo: " + message)
}
ws.onClose { session, statusCode, reason -> println("Closed") }
ws.onError { session, throwable -> println("Errored") }
}
app.ws("/websocket", ws -> {
ws.onConnect(session -> System.out.println("Connected"));
ws.onMessage((session, message) -> {
System.out.println("Received: " + message);
session.getRemote().sendString("Echo: " + message);
});
ws.onClose((session, statusCode, reason) -> System.out.println("Closed"));
ws.onError((session, throwable) -> System.out.println("Errored"));
});
Object mapping
- Kotlin
- Java
var todos = arrayOf(...)
app.get("/todos") { ctx -> // map array of Todos to json-string
ctx.json(todos)
}
app.put("/todos") { ctx -> // map request-body (json) to array of Todos
todos = ctx.bodyAsClass(Array<Todo>::class.java)
ctx.status(204)
}
Todo[] todos = ...
app.get("/todos", ctx -> { // map array of Todos to json-string
ctx.json(todos);
});
app.put("/todos", ctx -> { // map request-body (json) to array of Todos
todos = ctx.bodyAsClass(Todo[].class);
ctx.status(204);
});
Uploads
- Kotlin
- Java
app.post("/upload") { ctx ->
ctx.uploadedFiles("files").forEach { (contentType, content, name, extension) ->
FileUtils.copyInputStreamToFile(content, File("upload/" + name))
}
}
app.post("/upload", ctx -> {
ctx.uploadedFiles("files").forEach(file -> {
copyInputStreamToFile(file.getContent(), new File("upload/" + file.getName()));
});
});
Kotlin and Java interoperability
The interoperability between Kotlin and Java is very important to Javalin. When moving a Javalin project from Java to Kotlin, you shouldn’t need to learn a new way of doing things. In the above examples you can switch between Kotlin and Java and see that everything is more or less the same, except for a few parens and semicolons. To maintain this consistent API for both languages is an important goal of the project.
Main features
- Lightweight - You don’t have to learn any advanced concepts to get started
- Consistent API - All handlers and mappers are void and operate on the Context (ctx)
- Almost identical API for both Kotlin and Java
- Not opinionated - A library rather than a framework (you never have to extend anything)
- Fully customizable embedded server (Jetty)
- JSON-object-mapping (via Jackson)
- Simple per-endpoint auth via
AccessManager
interface - Simple static file handling
- Lifecycle events
- CookieStore - An easy way to serialize and store objects in cookies
- Template rendering (Velocity, Freemarker, Thymeleaf, Mustache)
- Markdown rendering
Get involved
If you want to contribute to the project, head on over to GitHub.
No breaking changes since 0.5.0
If you’re currently using a 0.5.X version of Javalin, upgrading to 1.0.0 should not break anything.