Strange library problem..

Discussion in 'Plugin Development' started by gdude2002, Jul 1, 2012.

  1. Offline


    My BukkitDev Profile
    My Plugins (3) profile:
    My Plugins (CFCOUNT)
    Minecraft account:

    Please note: I feel like this is not a Clojure-specific problem. If you think it is, please feel free to say so, but it may be possible that I'm just doing something silly Java-wise and need to be slapped around a bit.

    I have been discussing this problem in two places: Github and StackOverflow.

    As a person that uses Clojure at work, and knowing that it has superb Java interoptability, I thought it would be trivial to write a Bukkit plugin in it. Considering Clojure provides methods for compiling Clojure to Java classes, it seems to make sense. However, Bukkit appears unable to find Clojure.

    (Yes, I copied some of this from my own post on StackOverflow to make sure they'd look good. :3
    The reason I'm posting it here too is because people here are far more likely to have Bukkit experience.)

    So, I made a simple class in Clojure, as follows..

    Code (Text):
    1. (ns com.gdude2002.ClojurePlugin.mainclj
    2.   (:gen-class
    3.   :name com.gdude2002.ClojurePlugin.mainclj
    4.   :extends
    5.   (:import
    7. (defn -onEnable [this] (java.util.logging.Logger/getLogger "Loaded clojure plugin!"))
    8. (defn -onDisable [this] (java.util.logging.Logger/getLogger "Unloaded clojure plugin!"))

    This compiles to the following (decompiled) class..

    Code (Text):
    1. // IntelliJ API Decompiler stub source generated from a class file
    2. // Implementation of methods is not available
    4. package com.gdude2002.ClojurePlugin;
    6. public class mainclj extends {
    7.     private static final clojure.lang.Var main__var;
    8.     private static final clojure.lang.Var onEnable__var;
    9.     private static final clojure.lang.Var getResource__var;
    10.     private static final clojure.lang.Var onLoad__var;
    11.     private static final clojure.lang.Var getLogger__var;
    12.     private static final clojure.lang.Var saveDefaultConfig__var;
    13.     private static final clojure.lang.Var getDescription__var;
    14.     private static final clojure.lang.Var removeDDL__var;
    15.     private static final clojure.lang.Var onDisable__var;
    16.     private static final clojure.lang.Var isInitialized__var;
    17.     private static final clojure.lang.Var saveResource__var;
    18.     private static final clojure.lang.Var onCommand__var;
    19.     private static final clojure.lang.Var getDefaultWorldGenerator__var;
    20.     private static final clojure.lang.Var toString__var;
    21.     private static final clojure.lang.Var getDataFolder__var;
    22.     private static final clojure.lang.Var installDDL__var;
    23.     private static final clojure.lang.Var getDatabase__var;
    24.     private static final clojure.lang.Var getFile__var;
    25.     private static final clojure.lang.Var getClassLoader__var;
    26.     private static final clojure.lang.Var getCommand__var;
    27.     private static final clojure.lang.Var getDatabaseClasses__var;
    28.     private static final clojure.lang.Var getConfig__var;
    29.     private static final clojure.lang.Var reloadConfig__var;
    30.     private static final clojure.lang.Var clone__var;
    31.     private static final clojure.lang.Var setEnabled__var;
    32.     private static final clojure.lang.Var saveConfig__var;
    34.     public mainclj() { /* compiled code */ }
    36.     public getDataFolder() { /* compiled code */ }
    38.     public boolean onCommand(org.bukkit.command.CommandSender p0, org.bukkit.command.Command p1, java.lang.String p2, java.lang.String[] p3) { /* compiled code */ }
    40.     public void reloadConfig() { /* compiled code */ }
    42.     public org.bukkit.configuration.file.FileConfiguration getConfig() { /* compiled code */ }
    44.     public getFile() { /* compiled code */ }
    46.     public void saveConfig() { /* compiled code */ }
    48.     public org.bukkit.command.PluginCommand getCommand(java.lang.String p0) { /* compiled code */ }
    50.     public void onEnable() { /* compiled code */ }
    52.     public java.util.logging.Logger getLogger() { /* compiled code */ }
    54.     public void onLoad() { /* compiled code */ }
    56.     public java.lang.ClassLoader getClassLoader() { /* compiled code */ }
    58.     public void saveDefaultConfig() { /* compiled code */ }
    60.     public org.bukkit.plugin.PluginDescriptionFile getDescription() { /* compiled code */ }
    62.     public com.avaje.ebean.EbeanServer getDatabase() { /* compiled code */ }
    64.     public void removeDDL() { /* compiled code */ }
    66.     public void onDisable() { /* compiled code */ }
    68.     public boolean isInitialized() { /* compiled code */ }
    70.     public org.bukkit.generator.ChunkGenerator getDefaultWorldGenerator(java.lang.String p0, java.lang.String p1) { /* compiled code */ }
    72.     public void installDDL() { /* compiled code */ }
    74.     public void saveResource(java.lang.String p0, boolean p1) { /* compiled code */ }
    76.     public java.util.List getDatabaseClasses() { /* compiled code */ }
    78.     public java.lang.String toString() { /* compiled code */ }
    80.     public java.lang.Object clone() { /* compiled code */ }
    82.     public void setEnabled(boolean p0) { /* compiled code */ }
    84.     public getResource(java.lang.String p0) { /* compiled code */ }
    86.     public static void main(java.lang.String[] p0) { /* compiled code */ }
    87. }

    I use clojure's compile function to compile this to a Java class, as follows..
    Code (Text):
    1. (set! *compile-path* ".")
    2. (compile 'com.gdude2002.ClojurePlugin.mainclj)
    I then put it in the jar manually, under com/gdude2002/ClojurePlugin/mainclj.class (as well as putting the plugin.yml in the root).
    -- So far so good. This method isn't making bukkit bitch about my code (specifically), which I guess is a good thing. Now, on to the problem.
    When I try to launch the server with this handmade jar, I get the following output.
    Code (Text):
    1. 21:43:30 [SEVERE] Could not load 'plugins\plugin.jar' in folder 'plugins'
    2. org.bukkit.plugin.InvalidPluginException: java.lang.NoClassDefFoundError: clojure/lang/IFn
    "So," I think, "That seems simple enough - it can't find Clojure, right?" So, I put the clojure jar in all sorts of places, with the same error. I also add META-INF/MANIFEST.MF to the jar, containing Class-Path: ../lib. Still nothing.
    So, thinking I was being smart, I pulled the clojure folder out of the Clojure jar and shoved it into mine, also putting the folder in ../lib, and other places I thought it might help.
    Now, I get this error..
    Code (Text):
    1. 21:51:33 [SEVERE] Could not load 'plugins\plugin.jar' in folder 'plugins'
    2. org.bukkit.plugin.InvalidPluginException: java.lang.ExceptionInInitializerError
    3. ...
    4. Caused by: Could not locate clojure/core__init.class or clojure/core.clj on classpath:
    5. ...
    The thing is, both of those things exist, as far as I can see..

    I know, there's no project.clj file above. Thing is, I don't have one! I'm running the compile.clj on mainclj.clj directly, and creating a jarfile by hand.
    At this point, I'm entirely stumped. I feel so close, and yet, so far away..

    Anyone got any ideas? Any help at all is much appreciated.

    EDIT: It has been noted that the build method doesn't seem to make a difference, as noted by one user on StackOverflow.

    EDIT 2: It may also be worth noting that I only know some very basic Java. I can Clojure, but this is the first time I've used Java. :p
  2. Offline


    My BukkitDev Profile
    My Plugins (1) profile:
    My Plugins (CFCOUNT)
    Minecraft account:
    Okay, i have no idea what clojure is, however it looks like a sort of scripting/programming language that works with java (or CAN work with java)

    I dont know much about it, but lets go over the bukkit basics.

    what does your plugin.yml file look like?
  3. Offline


    My BukkitDev Profile
    My Plugins (3) profile:
    My Plugins (CFCOUNT)
    Minecraft account:
    Here you go:

    Code (Text):
    1. name: ClojurePlugin
    2. main: com.gdude2002.ClojurePlugin.mainclj
    3. version: 0.0.1
    Clojure is a lisp-like language that runs on top of Java, which means I can do things like call Java code directly within it, or compile it to Java classes.
  4. Offline


    My BukkitDev Profile
    My Plugins (3) profile:
    My Plugins (CFCOUNT)
    Minecraft account:

    Nobody has any ideas?
  5. Offline


    My BukkitDev Profile
    My Plugins (8) profile:
    My Plugins (CFCOUNT)
    Minecraft account:
    you need to include those classes inside your plugin.jar
  6. Offline


    My BukkitDev Profile
    My Plugins (3) profile:
    My Plugins (CFCOUNT)
    Minecraft account:
    Oh, of course, the generated class isn't including the Clojure stuff..

    Great, thanks, I'll look into that when I get home

Share This Page