Strange library problem..

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

Thread Status:
Not open for further replies.
  1. Hiya!

    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..

    (ns com.gdude2002.ClojurePlugin.mainclj
      :name com.gdude2002.ClojurePlugin.mainclj
    (defn -onEnable [this] (java.util.logging.Logger/getLogger "Loaded clojure plugin!"))
    (defn -onDisable [this] (java.util.logging.Logger/getLogger "Unloaded clojure plugin!"))

    This compiles to the following (decompiled) class..

    // IntelliJ API Decompiler stub source generated from a class file
    // Implementation of methods is not available
    package com.gdude2002.ClojurePlugin;
    public class mainclj extends {
        private static final clojure.lang.Var main__var;
        private static final clojure.lang.Var onEnable__var;
        private static final clojure.lang.Var getResource__var;
        private static final clojure.lang.Var onLoad__var;
        private static final clojure.lang.Var getLogger__var;
        private static final clojure.lang.Var saveDefaultConfig__var;
        private static final clojure.lang.Var getDescription__var;
        private static final clojure.lang.Var removeDDL__var;
        private static final clojure.lang.Var onDisable__var;
        private static final clojure.lang.Var isInitialized__var;
        private static final clojure.lang.Var saveResource__var;
        private static final clojure.lang.Var onCommand__var;
        private static final clojure.lang.Var getDefaultWorldGenerator__var;
        private static final clojure.lang.Var toString__var;
        private static final clojure.lang.Var getDataFolder__var;
        private static final clojure.lang.Var installDDL__var;
        private static final clojure.lang.Var getDatabase__var;
        private static final clojure.lang.Var getFile__var;
        private static final clojure.lang.Var getClassLoader__var;
        private static final clojure.lang.Var getCommand__var;
        private static final clojure.lang.Var getDatabaseClasses__var;
        private static final clojure.lang.Var getConfig__var;
        private static final clojure.lang.Var reloadConfig__var;
        private static final clojure.lang.Var clone__var;
        private static final clojure.lang.Var setEnabled__var;
        private static final clojure.lang.Var saveConfig__var;
        public mainclj() { /* compiled code */ }
        public getDataFolder() { /* compiled code */ }
        public boolean onCommand(org.bukkit.command.CommandSender p0, org.bukkit.command.Command p1, java.lang.String p2, java.lang.String[] p3) { /* compiled code */ }
        public void reloadConfig() { /* compiled code */ }
        public org.bukkit.configuration.file.FileConfiguration getConfig() { /* compiled code */ }
        public getFile() { /* compiled code */ }
        public void saveConfig() { /* compiled code */ }
        public org.bukkit.command.PluginCommand getCommand(java.lang.String p0) { /* compiled code */ }
        public void onEnable() { /* compiled code */ }
        public java.util.logging.Logger getLogger() { /* compiled code */ }
        public void onLoad() { /* compiled code */ }
        public java.lang.ClassLoader getClassLoader() { /* compiled code */ }
        public void saveDefaultConfig() { /* compiled code */ }
        public org.bukkit.plugin.PluginDescriptionFile getDescription() { /* compiled code */ }
        public com.avaje.ebean.EbeanServer getDatabase() { /* compiled code */ }
        public void removeDDL() { /* compiled code */ }
        public void onDisable() { /* compiled code */ }
        public boolean isInitialized() { /* compiled code */ }
        public org.bukkit.generator.ChunkGenerator getDefaultWorldGenerator(java.lang.String p0, java.lang.String p1) { /* compiled code */ }
        public void installDDL() { /* compiled code */ }
        public void saveResource(java.lang.String p0, boolean p1) { /* compiled code */ }
        public java.util.List getDatabaseClasses() { /* compiled code */ }
        public java.lang.String toString() { /* compiled code */ }
        public java.lang.Object clone() { /* compiled code */ }
        public void setEnabled(boolean p0) { /* compiled code */ }
        public getResource(java.lang.String p0) { /* compiled code */ }
        public static void main(java.lang.String[] p0) { /* compiled code */ }

    I use clojure's compile function to compile this to a Java class, as follows..
    (set! *compile-path* ".")
    (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.
    21:43:30 [SEVERE] Could not load 'plugins\plugin.jar' in folder 'plugins'
    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..
    21:51:33 [SEVERE] Could not load 'plugins\plugin.jar' in folder 'plugins'
    org.bukkit.plugin.InvalidPluginException: java.lang.ExceptionInInitializerError
    Caused by: Could not locate clojure/core__init.class or clojure/core.clj on classpath:
    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. 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. Here you go:

    name: ClojurePlugin
    main: com.gdude2002.ClojurePlugin.mainclj
    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. Bamp.

    Nobody has any ideas?
  5. you need to include those classes inside your plugin.jar
  6. Oh, of course, the generated class isn't including the Clojure stuff..

    Great, thanks, I'll look into that when I get home
Thread Status:
Not open for further replies.

Share This Page