Skip to content

Repository files navigation

Librarian

A runtime dependency management library for Java projects, primarily designed for Java-based Minecraft server plugins.

Libraries can be downloaded from Maven repositories (or direct URLs) into a plugin's data folder, relocated and then loaded into the plugin's classpath at runtime.

Or you can use the automatic Gradle integration with the Gradle plugin.

Why use runtime dependency management?

Hosting services like SpigotMC limit plugin file size, and bundling dependencies can push a plugin over that limit. With runtime dependency management, dependencies are downloaded and cached by the server instead of being bundled, keeping the plugin jar small. That also means faster downloads and less bandwidth strain when self-hosting.

Maven Central and other public repositories note

Librarian downloads dependencies from remote repositories at runtime, on every server that runs your plugin. Pointing it at Maven Central (or other public repositories such as Sonatype) effectively uses them as a CDN to serve dependencies to end users, which their infrastructure is not meant for.

Host your own mirror of the repositories you depend on and configure Librarian to use it instead. This keeps traffic on infrastructure you control and avoids upstream availability or rate-limiting issues.

Note that when using the Gradle plugin, Librarian will automatically replace Maven Central with its Google mirror, which can be overridden using the mavenCentralRepositoryUrl variable in the librarian extension block.

Usage

Add the repository and dependency (Gradle example):

maven { url = uri("https://repo.kyngs.xyz/public/") }
implementation("xyz.kyngs.librarian:librarian-paper:2.0.0-SNAPSHOT") // replace paper with your platform

Always relocate Librarian to avoid conflicts:

relocate("xyz.kyngs.librarian", "your.package.lib.librarian")

Create a LibraryManager for your platform:

PaperLibraryManagerlibraryManager = newPaperLibraryManager(plugin);

Build a Library:

Librarylib = Library.builder()
.groupId("your{}dependency{}groupId") // "{}" becomes ".", avoiding relocation by shade
.artifactId("artifactId")
.version("version")
// the rest are optional:
.id("my-lib") // libraries sharing an id load into a common IsolatedClassLoader
.relocate("package{}to{}relocate", "the{}relocated{}package")
.isolatedLoad(true)
.classifier("customClassifier")
.checksum("Base64-encoded SHA-256 checksum")
.build();

Add a repository, then download and load the library. loadLibrary handles both:

libraryManager.addMavenCentral();
libraryManager.loadLibrary(lib);

Gradle plugin

The Gradle plugin lets you declare Librarian dependencies in your build script instead of specifying them manually in code. On build, it generates a librarian.json inside your JAR listing all dependencies (including transitive ones) and their repositories, which Librarian loads at runtime.

Adding the plugin

Add the plugin repository in settings.gradle:

pluginManagement {
repositories {
maven {
url = uri("https://repo.kyngs.xyz/gradle-plugins")
}
gradlePluginPortal()
}
}

Then apply it in build.gradle:

plugins {
id 'xyz.kyngs.librarian.plugin' version '1.2.1'
}

Declaring dependencies

Replace the compileOnly configuration with librarian:

dependencies {
librarian 'com.zaxxer:HikariCP:5.0.1'
}

The librarian task, run automatically on build, writes the librarian.json described above into the final JAR.

Linking with Librarian

The plugin only generates librarian.json; you still have to load it. Call LibraryManager.configureFromJSON() to do so.

Further configuration

Relocating

Relocation is important when bundling libraries. Add the shadow plugin alongside Librarian:

plugins {
id 'com.github.johnrengelman.shadow' version '8.1.1'
id 'xyz.kyngs.librarian.plugin' version '1.2.1'
}

Then define the relocation rules:

shadowJar {
relocate 'com.zaxxer.hikari', 'com.example.hikari'
}

See the shadow plugin documentation for details.

If you use relocation, you must build with the shadowJar task.

Excluding dependencies

The plugin resolves all transitive dependencies, some of which may be unnecessary. For example, com.zaxxer:HikariCP pulls in org.slf4j:slf4j-api, which platforms like Bukkit already bundle, so downloading it is redundant and can cause conflicts.

Exclude a dependency with a regular expression matched against each dependency id (groupId:artifactId:version):

librarian {
excludeDependency 'org.slf4j:.*:.*'
}

The example above excludes everything in the org.slf4j group.

Credits

Special thanks to:

About

A runtime dependency management library for plugins running in Java-based Minecraft server platforms.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages