Implementing a Web API with Javalin
CS 240 – Advanced Software Construction
Javalin Overview
Javalin
A Simple Javalin Server
import io.javalin.Javalin;
public class SimpleHelloBYUServer {
public static void main(String[] args) {
Javalin.create()
.get("/hello",
ctx -> ctx.result("Hello BYU!"))
.start(8080);
}
}
-------------
Alternative Handler Implementation: Method Reference
public class SimpleHelloBYUServer {
public static void main(String[] args) {
Javalin.create()
.get("/hello", SimpleHelloBYUServer::handleHello)
.start(8080);
}
private static void handleHello(Context ctx) {
ctx.result("Hello BYU!");
}
}
Alternative Handler Implementation: Handler Class
public class SimpleHelloBYUServer {
public static void main(String[] args) {
Javalin.create()
.get("/hello", new HelloHandler())
.start(8080);
}
private static class HelloHandler implements Handler {
@Override
public void handle(@NotNull Context ctx)
throws Exception {
ctx.result("Hello BYU!");
}
}
}
Javalin Server with Handler Classes
public class HelloBYUServer {
public static void main(
String[] args) {
int requestedPort =
Integer.parseInt(args[0]);
var server =
new HelloBYUServer();
int port =
server.run(requestedPort);
System.out.println(
"Running on port " + port);
}
public int run(int requestedPort) {
Javalin javalinServer =
Javalin.create();
createHandlers(javalinServer);
javalinServer.start(
requestedPort);
return javalinServer.port();
}
private void createHandlers(
Javalin javalinServer) {
javalinServer.get("/hello",
new HelloBYUHandler());
// Other routes here
}
}
Simple Handler Class
import io.javalin.http.Context;
import io.javalin.http.Handler;
public class HelloBYUHandler implements Handler {
public void handle(Context context) {
context.result("Hello BYU!");
}
}
Simple Json Handler Class
import io.javalin.http.Context;
import io.javalin.http.Handler;
public class HelloBYUJsonHandler implements Handler {
public void handle(Context context) {
context.json("{message: Hello BYU!}");
}
}
Detailed Handler Class
import io.javalin.http.Context;
import io.javalin.http.Handler;
public class HelloBYUJsonHandler implements Handler {
public void handle(Context context) {
context.status(200);
context.contentType("application/json");
context.header("CS240", "Awesome!");
context.result("{message: Hello BYU!}");
}
}
Handlers
AKA: Routes
Endpoint Handlers
get("/", (ctx) -> {
// Show something
});
post("/", (ctx) -> {
// Create something
});
put("/", (ctx) -> {
// Update something
});
delete("/", (ctx) -> {
// Delete something
});
Handlers are matched in the order they are defined. The first handler that matches the request is invoked.
Before and After Handlers
before(context -> {
boolean authenticated;
// ... check if authenticated
if (!authenticated) {
throw new UnauthorizedResponse();
}
});
Before and After Handlers (continued)
before("/protected/*", context -> {…});
Named Parameters
// matches "GET /hello/foo" and "GET /hello/bar" get("/hello/{name}", context -> {
return "Hello: " + context.pathParam("name");
});
// matches "GET /hello/foo/bar"
get("/hello/<name>", context -> {
return "Hello: " + context.pathParam("name");
});
<...> allows slashes, {...} does not allow slashes
Wildcard Parameters
// matches "GET /hello/foo/bar"
get("/hello/*", context -> {
// url part matching * not available
// (use<...> syntax to access
});
Useful Request and Response Methods
Request
Response
See: https://javalin.io/documentation#context for complete list
Error Handling
Error Handling
app.exception(Exception.class, (e, ctx) -> {
// handle general exceptions here
// will not trigger if more specific exception-mapper found
});
app.error(404, ctx -> {
ctx.result("Generic 404 message");
});
Throwing Responses
Error Handling Example
private void run() {
Javalin.create()
.get("/error", this::throwException)
.exception(Exception.class, this::exceptionHandler)
.error(404, this::notFound)
.start(8080);
}
private void throwException(Context context) {
throw new RuntimeException("The server is on fire!");
}
private void exceptionHandler(Exception e, Context context) {
var body = new Gson().toJson(Map.of("message",
String.format("Error: %s", e.getMessage()), "success", false));
context.status(500);
context.json(body);
}
private void notFound(Context context) {
String msg = String.format("[%s] %s not found", context.method(), context.path());
var body = new Gson().toJson(Map.of("message", String.format("Error: %s", msg), "success", false));
context.json(body);
}
Serving Static Files
Serving Static Files / Web Applications
import io.javalin.Javalin;
public class StaticFileServer {
…
public int run(int requestedPort) {
Javalin javalinServer = Javalin.create(
config -> config.staticFiles.add("web")
);
…
}
…
}
Serving Static Files (cont.)
Installation
Making Javalin Available to Your Project
Three Ways:
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>
<version>6.4.0</version>
</dependency>
implementation group: 'io.javalin', name: 'javalin', version: '6.4.0'