Skip to content

Replace Spark with Jetty 12 and virtual threads - #5

Merged
SrBedrock merged 14 commits into
masterfrom
refactor/jetty-12
Oct 5, 2026
Merged

SrBedrock merged 14 commits into
masterfrom
refactor/jetty-12

Conversation

@SrBedrock

@SrBedrock SrBedrock commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Summary

Replace Spark Java / Jetty 9 with direct Jetty 12.1.13 integration and use Jetty's native server capabilities where they match the existing REST API semantics.

Jetty 12 migration

  • remove com.sparkjava:spark-core and the old Jetty 9 stack
  • embed and shade org.eclipse.jetty:jetty-server:12.1.13
  • remove the obsolete Jetty 9 NoLogging adapter and log4j.properties
  • keep SLF4J unshaded so Jetty uses the logging backend provided by Paper
  • preserve the existing JSON response contract and REST paths:
    • GET /server/{placeholder}
    • GET /{uuid}/{placeholder}

Java 25 virtual threads

Jetty keeps its internal work on QueuedThreadPool while a managed VirtualThreadPool is configured as the virtual-thread executor. Blocking application handlers therefore run through Jetty's adaptive execution strategy without moving PlaceholderAPI work onto the Minecraft main thread.

Reload lifecycle operations also use a dedicated single virtual-thread executor rather than the common ForkJoinPool.

Native Jetty features adopted

  • Routing: PathMappingsHandler.NoContext + UriTemplatePathSpec replace Spark routing.
  • Concurrency: QoSHandler replaces the custom Semaphore; max-concurrent remains fail-fast with JSON HTTP 503 and no suspended request queue.
  • IP allowlist: InetAccessHandler replaces manual socket-peer checks and adds native address/CIDR pattern support while still using the real connection address rather than forwarded headers.
  • Graceful shutdown: GracefulHandler drains in-flight requests while rejecting new work with JSON HTTP 503. shutdown-timeout-ms defaults to 5000 ms and is valid from 100 to 30000 ms.
  • Lifecycle: direct Jetty Server / ServerConnector lifecycle replaces Spark initialization and shutdown wrappers.

Intentionally retained application logic

  • Fixed-window rate limiting: Jetty's DoSHandler uses rate/leaky-bucket semantics, which is not equivalent to the existing rate-limit.requests + arbitrary window-seconds contract. RequestLimiter is retained to avoid a behavioral/configuration change.
  • Token authentication: the existing Token header and constant-time comparison remain because Jetty's general security framework would add unnecessary machinery and change the API authentication model.
  • JSON serialization: Gson remains responsible for the legacy {status,message} payload.

Threading behavior

Both player and server placeholder endpoints remain off the Minecraft main thread:

  • player route: Bukkit.getOfflinePlayer(UUID) + PlaceholderAPI.setPlaceholders(...)
  • server route: PlaceholderAPI.setPlaceholders(null, ...)

Third-party PlaceholderAPI expansions queried by this service must support off-thread execution.

Validation

GitHub Actions passed on Java 25:

bash gradlew test shadowJar --no-daemon

The build includes compilation against Jetty 12.1.13, unit tests, and creation of the shaded plugin JAR.

@SrBedrock
SrBedrock marked this pull request as ready for review October 5, 2026 14:33
@SrBedrock
SrBedrock merged commit 335197f into master Oct 5, 2026
1 check passed
@SrBedrock
SrBedrock deleted the refactor/jetty-12 branch October 5, 2026 20:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant