From 36c4acb13a8b0765e685803e4cc818d41587f946 Mon Sep 17 00:00:00 2001 From: anthorob Date: Fri, 25 Sep 2026 06:36:00 -0400 Subject: [PATCH] Upgrade to Javalin 7 and refactor route registration Updated the dependency to Javalin v7.2.3 and refactored route registration to use the new `RoutesConfig` API. Adjusted `GuildRoutes`, `ActionRoutes`, and `WebApi` to align with updated conventions and centralized route definitions. Improved modularity, reduced redundancy, and ensured backward compatibility by migrating exception and error handler logic. Updated tests to comply with the refactored APIs and structure. --- pom.xml | 4 +-- .../http/server/ActionRoutes.java | 16 ++++----- .../http/server/GuildRoutes.java | 12 +++---- .../netneutrality/http/server/WebApi.java | 33 ++++++++++--------- .../netneutrality/http/WebModuleTest.java | 8 +++-- 5 files changed, 38 insertions(+), 35 deletions(-) diff --git a/pom.xml b/pom.xml index f66355e..a4e0c8e 100644 --- a/pom.xml +++ b/pom.xml @@ -162,7 +162,7 @@ io.javalin javalin - 6.7.0 + 7.2.3 @@ -202,7 +202,7 @@ gitlab4j-api 6.2.0 - + jakarta.servlet jakarta.servlet-api diff --git a/src/main/java/me/bobert/netneutrality/http/server/ActionRoutes.java b/src/main/java/me/bobert/netneutrality/http/server/ActionRoutes.java index 48a6f1a..f1d42da 100644 --- a/src/main/java/me/bobert/netneutrality/http/server/ActionRoutes.java +++ b/src/main/java/me/bobert/netneutrality/http/server/ActionRoutes.java @@ -6,7 +6,7 @@ package me.bobert.netneutrality.http.server; * https://discord.gg/qUa6zNFZsd */ -import io.javalin.Javalin; +import io.javalin.config.RoutesConfig; import io.javalin.http.Handler; import me.bobert.netneutrality.db.service.GuildServiceProvider; import net.dv8tion.jda.api.JDA; @@ -18,7 +18,7 @@ import java.util.Map; import java.util.function.Supplier; /** - * Registers the {@code /actions/*} endpoints on a {@link Javalin} instance. + * Registers the {@code /actions/*} endpoints on a {@link RoutesConfig} instance. */ public final class ActionRoutes { @@ -29,12 +29,12 @@ public final class ActionRoutes { } public static void register( - Javalin app, + RoutesConfig routes, Supplier jdaSupplier, GuildServiceProvider guildServices, Runnable shutdownHook ) { - app.get("/actions/status", ctx -> { + routes.get("/actions/status", ctx -> { JDA jda = GuildRoutes.jda(jdaSupplier); ctx.json(Map.of( "health", String.valueOf(jda.getStatus()), @@ -47,17 +47,17 @@ public final class ActionRoutes { ctx.result("Shutting down.."); scheduleShutdown(shutdownHook); }; - app.post("/actions/shutdown", shutdown); - app.get("/actions/shutdown", shutdown); + routes.post("/actions/shutdown", shutdown); + routes.get("/actions/shutdown", shutdown); - app.get("/actions/settings/current/{guildId}", ctx -> { + routes.get("/actions/settings/current/{guildId}", ctx -> { Guild guild = GuildRoutes.guild(jdaSupplier, ctx); Map settings = guildServices.get(guild).getGuildSettingService().getSettings(); ctx.json(Map.of("status", "ok", "settings", settings)); }); - app.post("/actions/settings/reload/{guildId}", ctx -> { + routes.post("/actions/settings/reload/{guildId}", ctx -> { Guild guild = GuildRoutes.guild(jdaSupplier, ctx); guildServices.get(guild).getGuildSettingService().reloadSettingsCache(); diff --git a/src/main/java/me/bobert/netneutrality/http/server/GuildRoutes.java b/src/main/java/me/bobert/netneutrality/http/server/GuildRoutes.java index 1b392b8..5ebf818 100644 --- a/src/main/java/me/bobert/netneutrality/http/server/GuildRoutes.java +++ b/src/main/java/me/bobert/netneutrality/http/server/GuildRoutes.java @@ -6,7 +6,7 @@ package me.bobert.netneutrality.http.server; * https://discord.gg/qUa6zNFZsd */ -import io.javalin.Javalin; +import io.javalin.config.RoutesConfig; import io.javalin.http.Context; import io.javalin.http.NotFoundResponse; import io.javalin.http.ServiceUnavailableResponse; @@ -18,27 +18,27 @@ import java.util.Map; import java.util.function.Supplier; /** - * Registers the read-only {@code /guilds/*} endpoints on a {@link Javalin} instance. + * Registers the read-only {@code /guilds/*} endpoints on a {@link RoutesConfig} instance. */ public final class GuildRoutes { private GuildRoutes() { } - public static void register(Javalin app, Supplier jdaSupplier) { - app.get("/guilds/owner", ctx -> ctx.json( + public static void register(RoutesConfig routes, Supplier jdaSupplier) { + routes.get("/guilds/owner", ctx -> ctx.json( jda(jdaSupplier).getGuilds().stream() .map(guild -> ordered("guild_id", guild.getId(), "owner_id", guild.getOwnerId())) .toList() )); - app.get("/guilds/channels/{guildId}", ctx -> ctx.json( + routes.get("/guilds/channels/{guildId}", ctx -> ctx.json( guild(jdaSupplier, ctx).getTextChannels().stream() .map(channel -> ordered("channel_id", channel.getId(), "channel_name", channel.getName())) .toList() )); - app.get("/guilds/roles/{guildId}", ctx -> ctx.json( + routes.get("/guilds/roles/{guildId}", ctx -> ctx.json( guild(jdaSupplier, ctx).getRoles().stream() .map(role -> ordered("channel_id", role.getId(), "channel_name", role.getName())) .toList() diff --git a/src/main/java/me/bobert/netneutrality/http/server/WebApi.java b/src/main/java/me/bobert/netneutrality/http/server/WebApi.java index 88d0f74..0a3fbf1 100644 --- a/src/main/java/me/bobert/netneutrality/http/server/WebApi.java +++ b/src/main/java/me/bobert/netneutrality/http/server/WebApi.java @@ -55,26 +55,27 @@ public class WebApi implements Lifecycle { int port = Integer.parseInt(settings.get("NETNEUTRALITY_API_PORT", "9000")); logger.info("Starting web server..."); + // Javalin 7 requires routes, exception and error handlers to be registered upfront. app = Javalin.create(config -> { config.jsonMapper(new GsonJsonMapper()); - config.showJavalinBanner = false; + config.startup.showJavalinBanner = false; + + config.routes.get("/", ctx -> ctx.html(LIVENESS_HTML)); + GuildRoutes.register(config.routes, jdaSupplier); + ActionRoutes.register(config.routes, jdaSupplier, guildServices, shutdownHook); + + config.routes.exception(HttpResponseException.class, (e, ctx) -> + ctx.status(e.getStatus()).json(Map.of("status", "error", "message", e.getMessage())) + ); + + config.routes.exception(Exception.class, (e, ctx) -> { + logger.error("Unhandled error while serving [{}]", ctx.path(), e); + ctx.status(500).json(Map.of("status", "error")); + }); + + config.routes.error(404, ctx -> ctx.json(Map.of("status", "error", "message", "Not found"))); }); - app.get("/", ctx -> ctx.html(LIVENESS_HTML)); - GuildRoutes.register(app, jdaSupplier); - ActionRoutes.register(app, jdaSupplier, guildServices, shutdownHook); - - app.exception(HttpResponseException.class, (e, ctx) -> - ctx.status(e.getStatus()).json(Map.of("status", "error", "message", e.getMessage())) - ); - - app.exception(Exception.class, (e, ctx) -> { - logger.error("Unhandled error while serving [{}]", ctx.path(), e); - ctx.status(500).json(Map.of("status", "error")); - }); - - app.error(404, ctx -> ctx.json(Map.of("status", "error", "message", "Not found"))); - app.start(port); logger.info("Web server started on port [{}]", port); } diff --git a/src/test/java/me/bobert/netneutrality/http/WebModuleTest.java b/src/test/java/me/bobert/netneutrality/http/WebModuleTest.java index 0b0685f..221eb39 100644 --- a/src/test/java/me/bobert/netneutrality/http/WebModuleTest.java +++ b/src/test/java/me/bobert/netneutrality/http/WebModuleTest.java @@ -26,9 +26,11 @@ class WebModuleTest { @BeforeEach void setUp() { - server = Javalin.create(config -> config.showJavalinBanner = false); - server.get("/counter", ctx -> ctx.result("{\"hits\":" + hits.incrementAndGet() + "}")); - server.post("/counter", ctx -> ctx.result("{\"hits\":" + hits.incrementAndGet() + "}")); + server = Javalin.create(config -> { + config.startup.showJavalinBanner = false; + config.routes.get("/counter", ctx -> ctx.result("{\"hits\":" + hits.incrementAndGet() + "}")); + config.routes.post("/counter", ctx -> ctx.result("{\"hits\":" + hits.incrementAndGet() + "}")); + }); server.start(0); port = server.port(); }