BT

InfoQ Homepage News Introducing Javalin: a Lightweight Web Framework for Java and Kotlin

Introducing Javalin: a Lightweight Web Framework for Java and Kotlin

Bookmarks

Javalin is a lightweight web framework for Kotlin and Java designed to be simple and blocking by default, supporting WebSockets, HTTP2, and async requests. Javalin started as a fork of the SparkJava framework, but quickly turned into a ground-up rewrite influenced by the JavaScript framework koa.js.

Javalin is built on top of Jetty, and its performance is equivalent to raw Jetty code. Furthermore, developers do not need to extend any class, use @Annotations, or even download a different version of Javalin for Java and another for Kotlin.

To get started with Javalin using Java, developers only need to a public static void main as below:

public static void main(String[] args) {
    var app = Javalin.create().start(7000);
    app.get("/", ctx -> ctx.result("Hello World"));
}

Let's see a snippet with some configuration:

var app = Javalin.create(config -> {
    config.defaultContentType = "application/json";
    config.autogenerateEtags = true;
    config.addStaticFiles("/public");
    config.asyncRequestTimeout = 10_000L;
    config.dynamicGzip = true;
    config.enforceSsl = true;
}).routes(() -> {
    path("users", () -> {
        get(UserController::getAll);
        post(UserController::create);
        path(":user-id"(() -> {
            get(UserController::getOne);
            patch(UserController::update);
            delete(UserController::delete);
        });
        ws("events", userController::webSocketEvents);
    });
}).start(port);

It is pretty simple to validate parameters such as path params, query params, and form params on Javalin:

var myQpStr = ctx.queryParam("my-qp"); // no validation, returns String or null
var myQpInt = ctx.pathParam("my-qp", Integer.class).get(); // returns an Integer or throws
var myQpInt = ctx.formParam("my-qp", Integer.class).check(i -> i > 4).get(); // Integer > 4

// validate two dependent query parameters:
var fromDate = ctx.queryParam("from", Instant.class).get();
var toDate = ctx.queryParam("to", Instant.class)
        .check(it -> it.isAfter(fromDate), "'to' has to be after 'from'")
        .get();

// validate a json body:
var myObject = ctx.bodyValidator(MyObject.class)
        .check(obj -> obj.myObjectProperty == someValue)
        .get();

Another interesting feature of Javalin that exists in other frameworks, are Handlers. Javalin brings before-handlers, endpoint-handlers, after-handlers, exception-handlers and error-handlers.

//before handlers
app.before(ctx -> {
    // runs before all requests
});
app.before("/path/*", ctx -> {
    // runs before request to /path/*
});

//endpoint handlers
app.get("/", ctx -> {
    // some code
    ctx.json(object);
});

app.get("/hello/*, ctx -> {
    // capture all request to sub-paths of /hello/
});

//after handlers
app.after(ctx -> {
    // run after all requests
});
app.after("/path/*", ctx -> {
    // runs after request to /path/*
});

To handle authentication/authorization, Javalin brings the functional interface AccessManager, where developers can implement their own access-manager however they want.

// Set the access-manager that Javalin should use:
app.accessManager((handler, ctx, permittedRoles) -> {
    MyRole userRole = getUserRole(ctx);
    if (permittedRoles.contains(userRole)) {
        handler.handle(ctx);
    } else {
        ctx.status(401).result("Unauthorized");
    }
});

Role getUserRole(Context ctx) {
    // determine user role based on request
    // typically done by inspecting headers
}

enum MyRole implements Role {
    ANYONE, ROLE_ONE, ROLE_TWO, ROLE_THREE;
}

app.routes(() -> {
    get("/un-secured",   ctx -> ctx.result("Hello"),   roles(ANYONE));
    get("/secured",      ctx -> ctx.result("Hello"),   roles(ROLE_ONE));
});

Starting with version 3.0, Javalin also brings an OpenAPI (Swagger) plugin. The full implementation of the OpenAPI 3.0 specification is available both as a DSL and as annotations.

OpenAPI DSL:

val addUserDocs = document()
        .body()
        .result("400")
        .result("204")

fun addUserHandler(ctx: Context) {
    val user = ctx.body()
    UserRepository.addUser(user)
    ctx.status(204)
}

OpenAPI annotations:

@OpenApi(
    requestBody = OpenApiRequestBody(User::class),
    responses = [
        OpenApiResponse("400", Unit::class),
        OpenApiResponse("201", Unit::class)
    ]
)
fun addUserHandler(ctx: Context) {
    val user = ctx.body()
    UserRepository.createUser(user)
    ctx.status(201)
}

To deploy a Javalin application, developers just need to create a jar with dependencies (using maven-assembly-plugin), then launch the jar with java -jar filename.jar. Javalin has a Jetty embedded server, so no application server is necessary.

Javalin also has a page dedicated entirely to educators, where they emphasize that students can benefit from Javalin as there is no Servlet Container/Application Server configuration required for start coding , once there is an embedded Jetty server on Javalin.

There is a series of tutorials available, such as Running on GraalVM, and Kotlin CRUD REST API. The complete list can be found on the tutorials page.

More details on Javalin can be found on the documentation page. Users can download Javalin via maven or manually from maven central.

Rate this Article

Adoption
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Community comments

  • Benefits

    by Julius Fernandes /

    Your message is awaiting moderation. Thank you for participating in the discussion.

    What are the benefits of it over spring boot?

  • Re: Benefits

    by Daniel Bryant /

    Your message is awaiting moderation. Thank you for participating in the discussion.

    I think it's still early days for this framework, Julius, but I did see some related chatter last year on Reddit: www.reddit.com/r/java/comments/8htx7a/anyone_us...

  • Re: Benefits

    by Diogo Carleto /

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Hi Julius, I agree with Daniel.
    Anyway, I recommend you try Javalin, building a poc for example.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

BT

Is your profile up-to-date? Please take a moment to review and update.

Note: If updating/changing your email, a validation request will be sent

Company name:
Company role:
Company size:
Country/Zone:
State/Province/Region:
You will be sent an email to validate the new email address. This pop-up will close itself in a few moments.