Skip to content

chore: modernise codebase for Java 17 baseline#1070

Merged
confuser merged 4 commits intomasterfrom
chore/java17-modernisation
Apr 18, 2026
Merged

chore: modernise codebase for Java 17 baseline#1070
confuser merged 4 commits intomasterfrom
chore/java17-modernisation

Conversation

@confuser
Copy link
Copy Markdown
Member

Summary

Brings the codebase forward to take full advantage of the existing Java 17 toolchain bump and to remove a long tail of dependencies that no longer compile, build, or run cleanly.

This is mostly internal modernisation - no public-facing config or message keys change. User-visible runtime changes are documented in UPGRADE.md.

Changes

Test framework

  • Migrated every test from JUnit 4 + PowerMock to JUnit 5 (Jupiter).
  • Mockito 3.7.75.14.2; PowerMock dropped entirely.
  • javafaker 1.0.2datafaker 2.5.4 (javafaker is unmaintained).
  • hamcrest-library 1.2.1hamcrest 2.2; awaitility 4.0.14.3.0; mariaDB4j 2.6.03.3.1; jacoco 0.8.110.8.12.
  • Added BasePluginDbTest.requireCommand(name) helper so command tests declare the assumption once in @BeforeEach instead of repeating Assumptions.assumeTrue(cmd != null) per @Test.

Runtime libraries

  • HikariCP 6.3.3, ORMLite 6.1, MariaDB JDBC 3.5.7, MySQL Connector/J 8.4.0. H2 deferred to avoid an on-disk migration burden for existing users.
  • DatabaseConfig.getJDBCUrl() now emits driver-specific JDBC URLs (sslMode for MariaDB 3.x; drops the deprecated disableMariaDbDriver flag for MySQL 8.x).
  • SLF4J 1.x2.0.17 with a custom BanManagerSlf4jServiceProvider registered via META-INF/services. Bukkit shadowJar enables mergeServiceFiles() and relocates org.slf4j at task level so the ServiceLoader finds the relocated provider in the shaded JAR.
  • SnakeYAML 2.x: LoaderOptions configured with allowDuplicateKeys=true, 32 MiB code-point limit and depth=100 to keep older user-edited YAML loading without surprises.
  • bStats 3.2.1, PlaceholderAPI/Adventure refresh, Lombok 1.18.38.
  • ORMLite logging is now scoped via Logger.setGlobalLogLevel on the shaded backend rather than the global LOCAL_LOG_LEVEL system property, so other plugins' ORMLite is unaffected.

Language idioms

  • Plain DTOs converted to records: HistoryEntry, PlayerNameSummary, CommandInfo, Fetcher, UUIDFetcher, Hook, plus a unified Webhook record (replaces the previous WebhookHookConfig/WebhookData pair). Records use compact constructors for defensive copying of headers and pre/post hook lists.
  • httpClient field is now volatile for the double-checked init in BanManagerPlugin; HTTP/2 is the JDK default so the explicit version builder call is dropped. getHttpClient() carries thread-safety javadoc.
  • Pattern matching for instanceof, switch expressions in the SLF4J logger and RollbackSync, immutable factories (Set.of/List.of/Map.copyOf) where appropriate.
  • New StorageUtils.toSqlException helper to wrap the broader Exception thrown by ORMLite 6.x AutoCloseable resources, used by MigrationRunner, PlayerHistoryStorage, PlayerWarnStorage and InfoCommand. MigrationRunner.getCurrentVersion now logs unexpected exceptions at WARNING.

Test stability

  • IPUtilsTest swaps faker.internet().ipV6Address().replaceAll("0","") for a curated IPv6 sample set with canonical-form comparison; the previous random data occasionally produced invalid addresses.
  • forkEvery=1 stays on (and is documented inline) because several tests leak static state - JDBC drivers, native handles, daemon executors - that hangs the suite in a single JVM.

Documentation

  • New UPGRADE.md describing user-visible runtime changes (MariaDB JDBC scheme, MySQL Connector/J 8.x, SnakeYAML 2.x behaviour, bStats/PlaceholderAPI bumps, SLF4J 2.x on Bukkit).

Test plan

  • ./gradlew :BanManagerCommon:test - 439 tests, 0 failures, 0 errors, 14 skipped (platform-specific *All commands not registered on common, same as before the assumeTrue refactor).
  • Sequential ./gradlew build -x test produces every artifact across Bukkit, Bungee, Velocity, Sponge, and all 4 Fabric variants.
  • CI (build.yml + e2e.yml) green across all e2e platforms (Bukkit, BungeeCord, Velocity, Sponge 1.20.6/1.21.1/1.21.3, Fabric 1.20.1/1.21.1/1.21.4/1.21.11).
  • Smoke test on a real server for one of: MariaDB-backed install, MySQL-backed install (validates the new JDBC URL builder).

Companion PR

A matching modernisation PR will be opened against BanManager-WebEnhancer for its own dependency / JUnit 5 / Stonecutter sweep.

Brings the codebase forward to take full advantage of the existing
Java 17 toolchain bump and to remove a long tail of dependencies that
no longer compile, build, or run cleanly.

Test framework
- Migrate every test from JUnit 4 + PowerMock to JUnit 5 (Jupiter).
- Mockito 3.7.7 -> 5.14.2; drop PowerMock entirely.
- javafaker 1.0.2 -> datafaker 2.5.4 (javafaker is unmaintained).
- hamcrest-library 1.2.1 -> hamcrest 2.2; awaitility 4.0.1 -> 4.3.0;
  mariaDB4j 2.6.0 -> 3.3.1; jacoco 0.8.11 -> 0.8.12.
- Add BasePluginDbTest.requireCommand(name) helper so command tests
  declare the assumption once in @beforeeach instead of repeating
  Assumptions.assumeTrue(cmd != null) per @test.

Runtime libraries
- HikariCP 6.3.3, ORMLite 6.1, MariaDB JDBC 3.5.7, MySQL Connector/J
  8.4.0 (H2 deferred to avoid an on-disk migration). DatabaseConfig
  now emits driver-specific JDBC URLs (sslMode for MariaDB 3.x;
  drops the deprecated disableMariaDbDriver flag for MySQL 8.x).
- SLF4J 1.x -> 2.0.17 with a custom BanManagerSlf4jServiceProvider
  registered via META-INF/services. Bukkit shadowJar enables
  mergeServiceFiles() and relocates org.slf4j at task level so the
  ServiceLoader finds the relocated provider in the shaded JAR.
- SnakeYAML 2.x: configure LoaderOptions with allowDuplicateKeys=true,
  32 MiB code-point limit and depth=100 to keep older user-edited
  YAML loading without surprises.
- bStats 3.2.1, PlaceholderAPI/Adventure refresh, Lombok 1.18.38.
- ORMLite logging is now scoped via Logger.setGlobalLogLevel on the
  shaded backend rather than the global LOCAL_LOG_LEVEL system
  property, so other plugins' ORMLite is unaffected.

Language idioms
- Convert plain DTOs to records: HistoryEntry, PlayerNameSummary,
  CommandInfo, Fetcher, UUIDFetcher, Hook, and a unified Webhook
  record (replaces the previous WebhookHookConfig/WebhookData pair).
  Records use compact constructors for defensive copying of headers
  and pre/post hook lists.
- HttpClient field is now volatile for the double-checked init in
  BanManagerPlugin; HTTP/2 is the JDK default so the explicit version
  builder call is dropped. getHttpClient() carries thread-safety
  javadoc.
- Pattern matching for instanceof, switch expressions in the SLF4J
  logger and RollbackSync, immutable factories (Set.of/List.of/
  Map.copyOf) where appropriate.
- New StorageUtils.toSqlException helper to wrap the broader Exception
  thrown by ORMLite 6.x AutoCloseable resources, used by
  MigrationRunner, PlayerHistoryStorage, PlayerWarnStorage and
  InfoCommand. MigrationRunner.getCurrentVersion now logs unexpected
  exceptions at WARNING.

Test stability
- IPUtilsTest swaps faker.internet().ipV6Address().replaceAll("0","")
  for a curated IPv6 sample set with canonical-form comparison; the
  previous random data occasionally produced invalid addresses.
- forkEvery=1 stays on (and is documented inline) because several
  tests leak static state - JDBC drivers, native handles, daemon
  executors - that hangs the suite in a single JVM.

Documentation
- Add UPGRADE.md describing user-visible runtime changes (MariaDB
  JDBC scheme, MySQL Connector/J 8.x, SnakeYAML 2.x behaviour,
  bStats/PlaceholderAPI bumps, SLF4J 2.x on Bukkit).

Verification
- ./gradlew :BanManagerCommon:test - 439 tests, 0 failures, 0 errors,
  14 skipped (platform-specific *All commands not registered on
  common, same as before the assumeTrue refactor).
- Sequential ./gradlew build -x test produces every artifact across
  Bukkit, Bungee, Velocity, Sponge, and all 4 Fabric variants.
The libs ShadowJar and every platform ShadowJar were excluding
META-INF/services/** wholesale. That worked fine for MariaDB
Connector/J 2.x and HikariCP 4.x, which registered codecs and
drivers via static initialisers. After the modernisation bump to
mariadb-java-client 3.5.7 those pieces are loaded via ServiceLoader
and the missing META-INF/services entries surfaced at runtime as:

    java.sql.SQLException: Type java.lang.Boolean not supported type
        at me.confuser.banmanager.common.mariadb.BasePreparedStatement
            .trySetWithCodec(BasePreparedStatement.java:1331)

(every INSERT against a MariaDB server failed because the BooleanCodec
service entry was stripped from the relocated mariadb.plugin.Codec
service file).

Fix:

- libs ShadowJar: drop the blanket META-INF/services/** exclusion
  and add mergeServiceFiles() so each shaded dep's service file is
  merged into a single relocated entry. Verified contents include the
  java.sql.Driver registrations for the three drivers and ~30
  mariadb codec / auth / credential plugin entries, all rewritten to
  the me.confuser.banmanager.common.* package.

- bukkit / bungee / velocity / sponge / fabric ShadowJars: drop the
  same exclusion, add mergeServiceFiles(), and exclude :BanManagerLibs
  from minimisation so the codec / driver classes referenced only by
  the merged service files are not pruned. (For bukkit the
  minimisation list now also names the JDBC drivers, HikariCP and
  ORMLite explicitly to match the bukkit-specific include list.)

Local verification on all five plugin JARs:
- META-INF/services/java.sql.Driver lists the three relocated driver
  classes.
- META-INF/services/me.confuser.banmanager.common.mariadb.plugin.Codec
  carries the full codec list.
- BooleanCodec.class is present (5441 bytes on JVM-only platforms,
  5590 after Fabric remap).

E2E: the previous run failed on every platform with the BooleanCodec
error; this commit should restore the green state.
The BanManagerSlf4jServiceProvider implementation lives only in
bukkit/src/main/java/org/slf4j/impl/ and is renamed to
me.confuser.banmanager.common.slf4j.* by Bukkit's shadowJar relocation.

Other platforms inherit the bundled META-INF/services/org.slf4j.spi.SLF4JServiceProvider
entry from common (since bukkit/src/main/resources is a symlink to
common/src/main/resources) without ever shipping the implementation
class. On Fabric this crashes Minecraft's bootstrap when LogUtils
initialises SLF4J because the registered provider class can't be loaded.

Exclude org.slf4j.spi.SLF4JServiceProvider from the Fabric, Bungee,
Velocity and Sponge shaded JARs so they fall back to the SLF4J 2.x
implementation already provided by their host platform.
Not needed for this release.
@confuser confuser merged commit 470869d into master Apr 18, 2026
26 of 28 checks passed
@confuser confuser deleted the chore/java17-modernisation branch April 18, 2026 20:23
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