0
votes

I am working on a Plugin for an OpenFire Server. I am trying to integrate Spring into this plugin. When the plugin is initialized, I will like to call the Main Method for my Spring.

When I execute the Spring alone, it works fine, but when I call its main method from my plugin, I get an exception. How am I suppose to call the Spring Main Method. What am I missing. Any help will be appreciated. Thank you.

Spring Main Class:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        try {
            SpringApplication.run(Application.class, args);
            System.out.println("No error");
        } catch (Exception e) {
            System.out.println("Error " + e);

        }

    }
}

OpenFire Plugin:

public class FetchNewsPlugin implements Plugin {

    @Override
    public void initializePlugin(PluginManager manager, File pluginDirectory) {
        Runnable r = new Runnable() {
             public void run() {
                 String[] args = {};
                Application.main(args);
             }
         };

         new Thread(r).start();
         System.out.println("Plugin Intitialized");

    }

    @Override
    public void destroyPlugin() {
    }

}

Log Output:

Exception in thread "Thread-13" java.lang.NoClassDefFoundError: org/springframework/boot/SpringApplication at hello.Application.main(Application.java:11) at org.clinton.openfire.plugin.FetchNewsPlugin$1.run(FetchNewsPlugin.java:20) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.ClassNotFoundException: org.springframework.boot.SpringApplication at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 3 more

Where Exception is being thrown:

 /**
     * Finds and loads the class with the specified name from the URL search
     * path. Any URLs referring to JAR files are loaded and opened as needed
     * until the class is found.
     *
     * @param name the name of the class
     * @return the resulting class
     * @exception ClassNotFoundException if the class could not be found,
     *            or if the loader is closed.
     * @exception NullPointerException if {@code name} is {@code null}.
     */
    protected Class findClass(final String name)
        throws ClassNotFoundException
    {
        final Class result;
        try {
            result = AccessController.doPrivileged(
                new PrivilegedExceptionAction>() {
                    public Class run() throws ClassNotFoundException {
                        String path = name.replace('.', '/').concat(".class");
                        Resource res = ucp.getResource(path, false);
                        if (res != null) {
                            try {
                                return defineClass(name, res);
                            } catch (IOException e) {
                                throw new ClassNotFoundException(name, e);
                            }
                        } else {
                            return null;
                        }
                    }
                }, acc);
        } catch (java.security.PrivilegedActionException pae) {
            throw (ClassNotFoundException) pae.getException();
        }
        if (result == null) {
            throw new ClassNotFoundException(name);
        }
        return result;
    }
SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/home/clinton/git/Openfire/bin/build/lib/ant/slf4j-simple.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/home/clinton/git/Openfire/bin/build/lib/dist/slf4j-log4j12.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/home/clinton/git/Openfire/build/lib/ant/slf4j-simple.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/home/clinton/git/Openfire/build/lib/dist/slf4j-log4j12.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [org.slf4j.impl.SimpleLoggerFactory]
2

2 Answers

0
votes

It seems like you are using URLClassLoader to load classes that your needed. However, an URLClassLoader should contain all items or jars it depends on not only the jar itself.

In other words, you'd better extract your jar and add all necessary items to your URLClassLoader.

In this way it should work. And please let me know if any problem.

And question https://stackoverflow.com/a/37339725/5619827 could be helpful.

0
votes

Thanks @Gemini for helping, but I guess I was too dumb to follow his way. I found another workaround: Since the Spring could start successfully when executed alone. I bundled the Spring into a runnable jar file and executed using the following when th plugin starts:

private void startSpring() {
    try {
    ProcessBuilder processBuilder = new ProcessBuilder("/usr/lib/jvm/java-8-oracle/bin/java", "-jar", 
            "/home/clinton/git/Maven/target/mavenproject2-1.0-SNAPSHOT.jar");
    processBuilder.directory(new File("/home/clinton/git/Maven/Working"));
    File log = new File("log");
     processBuilder.redirectErrorStream(true);
     processBuilder.redirectOutput(Redirect.appendTo(log));
     Process p = processBuilder.start();
     assert processBuilder.redirectInput() == Redirect.PIPE;
     assert processBuilder.redirectOutput().file() == log;
     assert p.getInputStream().read() == -1;
    System.out.println("Started success");

        //Process p = processBuilder.start();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

I hope this helps someone too. I always find a way :)