(Optional) Advanced class loading

This section is only required for very advanced use cases, and 99% of all developers might not even know that this exists

Vital does some serious stuff regarding class loading and resource location to make all of its features and functionalities possible with Spigot, Paper and BungeeCord.
An effect of this is that some platform implementation specifics clash with the ones Vital uses, like duplicate resources in your plugin JAR file and in the server's runtime library, or logging providers, etc.

Here's an example. Let's say that you want to use a library in your plugin; that library happens to also be part of the server's runtime stack (So your server, like Spigot, Paper or BungeeCord, internally also uses this library).
Now when your server tries to load your plugin, your plugin now has access to two different implementations of that library, which one should it use?
The first thought would be to just use the one your plugin has, right?

Well yes, but actually no.
Because this introduces a weird problem.

Let's say that your plugin just uses the library it is shipped with.
Your plugin starts up, no problem, but now one of your players performs an action that calls the library you included (that clashes with your server).
IF the library you included contains everything it needs, this won't be a problem, but if the library is just an SPI and basically just an interface to call specific logic, you run into an error.

The best example of this is the SpigotAPI, PaperAPI and BungeeCordAPI.
All of these libraries are just interfaces for you to communicate with your server.
If you try to use them outside a Minecraft server, nothing happens, or an error is thrown.

Most of these issues can be fixed by simply adding your library as a compile-only dependency.

build.gradle.kts
dependencies {
  compileOnly("my.awesome.library:artifact:1.0.0")
}

But sometimes you have a library that transitively pulls in other artifacts, and then this solution won't do much.


To fix this, Vital already configures all it needs to get 99% of all plugins working, BUT if you are one of the unlucky 1%, this section might be your rescue.

Vital provides a hidden way to configure how resources and classes are loaded when it starts up.
You can use the vital.properties file to define class locations that should be loaded from the parent loader (your server's runtime) first, before attempting to load it from your plugin JAR.

Simply create this file in your resource location (so it is moved to your plugin JAR root when you build your plugin).
The following configuration is the default, any manual configurations are overridden and should always start with at least this:

vital.properties
vital.classloader.spigot.parent-first-packages=\
  org.bukkit, \
  net.kyori, \
  org.slf4j, \
  ch.qos.logback, \
  org.apache.logging
vital.classloader.paper.parent-first-packages=\
  org.bukkit, \
  net.kyori, \
  org.slf4j, \
  ch.qos.logback, \
  org.apache.logging
vital.classloader.bungee.parent-first-packages=\
  net.md_5.bungee, \
  org.slf4j, \
  ch.qos.logback, \
  org.apache.logging

What this configuration file does is, it tells Vital's internal class loader where to load specific classes or other resources from.
Here's how it works:

  1. Your plugin wants to use a specific class and automatically (you don't have to do anything. just use your stuff) loads the class it needs.
  2. Vital's internal class loader is used to load the class.
  3. It looks into the configuration file above and checks if the requested class or resource needs to be loaded from one of the configured locations.
  4. If the requested class or resource needs to be loaded from a location mentioned in this configuration file, Vital first asks Spigot, Paper or BungeeCord to load it.
  5. If Spigot, Paper or BungeeCord knows this class or resource, it is used. Nothing else happens anymore.
  6. But if Spigot, Paper or BungeeCord doesn't know the requested class or resource, Vital falls back to your plugin and tries to load it from your plugin JAR file.

Again, this section is only required for very advanced use cases, and 99% of all developers might not even know that this exists.

But, if you are experiencing class loading issues and this section did not resolve your issue, please open up an issue on GitHub immediately!

Found an issue?

Help us improve the documentation by reporting typos, missing information, or anything confusing.

Don't worry, we will auto-fill most of the annoying fields.

Create GitHub issue

This site and the Vital framework were built with ❤️ by Mike Neumann