Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to find Clojure

EDIT: There are some other discussions going on that are related to this question on the Bukkit forums and on Github.

So, I know one or two people have attempted this with no luck.. But I think I'm almost there.

One problem: I don't know Java, so this is a little alien to me. Anyway..

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

(ns com.gdude2002.ClojurePlugin.mainclj
  (:gen-class
   :name com.gdude2002.ClojurePlugin.mainclj
   :extends org.bukkit.plugin.java.JavaPlugin)
  (:import org.bukkit.plugin.java.JavaPlugin))

(defn -onEnable [this] (java.util.logging.Logger/getLogger "Loaded clojure plugin!"))
(defn -onDisable [this] (java.util.logging.Logger/getLogger "Unloaded clojure plugin!"))

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: java.io.FileNotFoundException: 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..

EDIT: Decided to show the decompiled class code here, in case that helps anyone.

// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available

package com.gdude2002.ClojurePlugin;

public class mainclj extends org.bukkit.plugin.java.JavaPlugin {
    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 java.io.File 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 java.io.File 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 java.io.InputStream getResource(java.lang.String p0) { /* compiled code */ }

    public static void main(java.lang.String[] p0) { /* compiled code */ }
}

EDIT: It was mentioned in the comments that I should post my project.clj file. 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. Does anyone have any ideas on this?

like image 597
gdude2002 Avatar asked Nov 14 '22 03:11

gdude2002


1 Answers

I solved this problem by configuring the class loader of the calling code as described in this post.

My situation might be a bit different as I did that from the calling Java code. In other words, I invoked that code in my CommandExecutor (Java) immediately before invoking a method from a class created using gen-class (Clojure).

like image 160
Jeb Avatar answered Nov 16 '22 02:11

Jeb