External JAR Dependency

Discussion in 'Plugin Development' started by EdGruberman, Jul 8, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    EdGruberman Retired Staff

    I have a plugin that depends on sqljdbc4.jar. Is there some way to make it available other than editing CraftBukkit's manifest.mf Class-Path?
  2. Offline


    I've been trying to figure this out too. One thing you can do is have users start craftbukkit with this:

    java -Xms512M -Xmx1G -cp sqljdbc4.jar;craftbukkit-0.0.1-SNAPSHOT.jar org.bukkit.craftbukkit.Main nogui
  3. Offline

    EdGruberman Retired Staff

    Oh yes, I forgot the command line class path option also. It seems kludgey still. I guess it's better than editing CraftBukkit's jar itself though.
    I'd love it if we were overlooking something simply/easy like editing the Class-Path in the plugin's manifest.mf file. But I've been unable to get that to work.
    Thank you for the reminder of the command line option. I think I'll go that route for now.
  4. Offline


    good job! you got it going...im having trouble D:
  5. Offline


    Use maven for your build environment, and use the maven-shade-plugin to include whatever externals JARs you need into your build JAR.
  6. Offline


    Putting the required jars into the server root directory does it.
  7. Offline

    EdGruberman Retired Staff

    maven-shade-plugin is an option I suppose also. though, if multiple plugins depend on it, it seems odd to package it into each one. i guess this possibility underlines the benefit of the command line option more.

    i did not have success just putting the jar in the server root directory (the directory with craftbukkit.jar). i had to edit the class-path also (manifest or -cp works though)
  8. Offline


    How could you use the start up classpath method on a mac? I cant seem to make it work although I can on windows?
  9. Offline


    If you're using maven, you can take a look at CommandHelper's pom file. I edit the classpath to look in several places for the WorldEdit plugin (a required dependency of CH). Also, for folks interested in having a single plugin, I also create a shaded jar, which includes WE directly inside. I'm still trying to figure out how to create multiple shaded jars though.

    If you are using ant to build your plugin (which I don't recommend, maven is much easier to work with) this approach can also be taken, though I don't know how to do it off hand.
  10. Offline

    EdGruberman Retired Staff

    It only took me 6 months, but eventually I got smarter and wanted to share in case anyone else stumbles upon this thread in the future.

    I've found two options that I like for different reasons/purposes.

    1 - Use the Class-Path attribute in the MANIFEST.MF file for your plugin and add a path to the jar. I'm honestly not sure why this wasn't working for me before, I must have been messing something else up. But it does work. If you use relative paths it will be from the folder the CraftBukkit jar runs from. e.g. In my standard setup I could add:
    Class-Path: plugins/<PluginName>/<ExternalJar>.jar
    2 - You can also use the URLClassLoader to point to a dynamically configured path at runtime to load whatever class you need from a particular jar. This even supports pointing directly to a class file or even an internet location.
  11. Offline


    add a dependency in the yaml?
  12. Offline

    EdGruberman Retired Staff

    plugin.yml dependencies are for other Bukkit plugins. If you have an external jar you are trying to include with your plugin, it's a different story.

    More on that second option I mentioned regarding URLClassLoader... It turns out you can use that to load a single class once. But your parent/system loader will not remember that jar if the class you loaded needs other classes out of that same jar.

    In my case, I found the following hack worked well:
                external = new File(plugin.getDataFolder(), "sqljdbc4.jar").toURI().toURL();
                loader = (URLClassLoader) ClassLoader.getSystemClassLoader();
                final Class<URLClassLoader> sysclass = URLClassLoader.class;
                final Method method = sysclass.getDeclaredMethod("addURL", URL.class);
                method.invoke(loader, new Object[] { external });
    Please be warned however, this really is a hack. I'm just not sure of an easier way to dynamically declare a reference to an external jar that will then load it's own classes further at runtime.

    There has got to be an easier/smarter/better way, haha.
Thread Status:
Not open for further replies.

Share This Page