Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Minecraft Plugin ClassNotFound Error from External JAR

I am trying to build a plugin for a Minecraft Spigot server that ultimately I would like to be able to communicate over serial with things connected to my PC (server is running locally on the PC as well).

I have been able to build and run the plugin and manipulate player/blocks in the game so I know the build process for my base plugin is working. My trouble started when I began trying to include an extra dependency: jSerialComm

I added the dependency entry in my pom.xml file:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

<dependency>
    <groupId>com.fazecast</groupId>
    <artifactId>jSerialComm</artifactId>
    <version>[2.0.0,3.0.0)</version>
    <scope>provided</scope>
</dependency>

I added some basic code to import classes from jSerialComm and do something basic with them inside of a command in my plugin:

import com.fazecast.jSerialComm.SerialPort;

public class CommandCheck implements CommandExecutor {

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (sender instanceof Player){
            System.out.println(SerialPort.getCommPorts());
        }
        return false;
    }
}

This builds fine, I’m using InteliJ and it does recognize the SerialPort class (no red underlines).

But when this command runs in the game I get a Class Not Found error:

org.bukkit.command.CommandException: Unhandled exception executing command 'check' in plugin MyFirstPlugin v1.0-SNAPSHOT
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:47) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:149) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
        at org.bukkit.craftbukkit.v1_18_R1.CraftServer.dispatchCommand(CraftServer.java:821) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1939) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1778) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1759) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:46) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:1) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.network.protocol.PlayerConnectionUtils.lambda$0(PlayerConnectionUtils.java:30) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.server.TickTask.run(SourceFile:18) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.util.thread.IAsyncTaskHandler.c(SourceFile:151) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.util.thread.IAsyncTaskHandlerReentrant.c(SourceFile:23) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1158) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.server.MinecraftServer.c(MinecraftServer.java:1) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.util.thread.IAsyncTaskHandler.y(SourceFile:125) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.server.MinecraftServer.bf(MinecraftServer.java:1137) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.server.MinecraftServer.y(MinecraftServer.java:1130) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.util.thread.IAsyncTaskHandler.c(SourceFile:134) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.server.MinecraftServer.x(MinecraftServer.java:1114) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:1038) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at net.minecraft.server.MinecraftServer.lambda$0(MinecraftServer.java:304) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
        at java.lang.Thread.run(Thread.java:833) [?:?]
Caused by: java.lang.NoClassDefFoundError: com/fazecast/jSerialComm/SerialPort
        at com.foamyguy.myfirstplugin.CommandCheck.onCommand(CommandCheck.java:21) ~[?:?]
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
        ... 21 more
Caused by: java.lang.ClassNotFoundException: com.fazecast.jSerialComm.SerialPort
        at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:147) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
        at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:99) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?]
        at com.foamyguy.myfirstplugin.CommandCheck.onCommand(CommandCheck.java:21) ~[?:?]
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
        ... 21 more

I have unzipped and looked inside of the built jar file and the jSerialComm jar file is successfully being included within my plugin jar:

unzipped jar contents

What do I need to do in order to successfully use an external JAR file (jSerialComm specifically) from inside of a Minecraft plugin? Or alternatively, is there some built-in way that I can connect and communicate over serial ports without needing an external JAR and therefore not needing anything "special" in order to work?

>Solution :

Even if the JAR is present in your plugin, the classes of the JAR are not loaded in the classpath and Spigot cannot access the classes.

You can use a plugin, such as the maven-shade-plugin, which copies all classes from your API-JAR to your Plugin-JAR.

First, set the scope from provided to compile.

<dependency>
    <groupId>com.fazecast</groupId>
    <artifactId>jSerialComm</artifactId>
    <version>[2.0.0,3.0.0)</version>
    <scope>compile</scope> <!-- -->
</dependency>

Then add the maven-shade-plugin under build > plugins inside your pom.xml

<build>
    <!-- ... -->
    <plugins>
      <!-- ... -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <!-- ... -->
    </plugins>
    <!-- ... -->
  </build>

If you now build the jar (using e. g. man clean package), there should be a "fat-" jar file in the target/ folder that contains the classes of the API as well as your classes.

Contents of your plugin before:

├ com
  ├ foamguy
    └ myfirstplugin
      └ ...
├ plugin.yml
└ jSerialComm-xxx.jar

Contents of your plugin after:

├ com
  ├ foamguy
    └ myfirstplugin
      └ ...
  └ fazecast
    └ jSerialComm
      └ ...
└ plugin.yml
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading