Загрузка динамического класса Java внутри веб-приложения

Я сделал проект Java, проект только этот класс:

package test.processor;

public abstract class Processor {

    public abstract void loadData(String objectId);
    public abstract void processData();
    public abstract void saveData(String objectId);

}

Проект экспортируется в виде jar-файла (processor.jar)

Затем я сделал еще один проект, который импортирует processor.jar, и есть класс, расширяющий Processor:

package test.process;

import test.processor.Processor;

public class Process extends Processor{

    @Override
    public void loadData(String objectId) {
        System.out.println("LOAD DATAAAAAAAAAAAA");     
    }

    @Override
    public void processData() {
        System.out.println("PROCESS DATAAAAAAAAAAAA");
    }

    @Override
    public void saveData(String objectId) {
        System.out.println("SAVE DATAAAAAAAAAAAA");
    }

}

Этот проект также экспортируется как jar (plugin.jar).

Наконец, я написал что-то для динамической загрузки плагинов:

import test.processor.Processor;

public class Test {

    public void testPlugins(){

        Processor plugin = (Processor) loadJar(
                "C:\\Users\\...\\Desktop\\plugin.jar",
                "test.process.Process");
        processor.loadData("dada");

    }

    private Object loadJar(String jar, String className){

        File jarFile = new File(jar);
        Object instance = null;
        try {
            URL jarpath = jarFile.toURI().toURL();
            String jarUrl = "jar:" + jarpath + "!/";
            URL urls[] = { new URL(jarUrl) };
            URLClassLoader child = new URLClassLoader(urls);
            Class classToLoad = Class.forName(nomeClasse, true, child);
            instance = classToLoad.newInstance();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return instance;

    }


} 

Если я запускаю этот код внутри основного метода, он работает правильно, и когда я пытаюсь запустить его на сервере, возникает проблема при загрузке класса, я получаю ClassNotFoundException (Processor). Я попытался поместить jar в tomcat/lib, project/WEB-INF/lib и ничего не изменилось.

Есть идеи, что я делаю не так?

1 ответ

Решение

Я решил не так, как хотел, но решил:

Сначала я попытался загрузить process.jar вручную:

private Object loadJars(String processJar, String pluginJar, String className){

    File processJarFile = new File(processJar);
    File pluginJarFile = new File(pluginJar);


    Object instance = null;
    try {

        URL processJarPath = processJarFile.toURI().toURL();
        String processJarUrl = "jar:" + processJarPath + "!/";

        URL pluginJarPath = pluginJarFile.toURI().toURL();
        String pluginJarUrl = "jar:" + pluginJarPath + "!/";


        URL urls[] = { new URL(processJarUrl), new URL(pluginJarUrl) };
        URLClassLoader child = new URLClassLoader(urls);
        Class classToLoad = Class.forName(nomeClasse, true, child);
        instance = classToLoad.newInstance();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return instance;

}

При корректной загрузке класса Process проблема возникает в методе testPlugins, когда он пытается привести к Processor (ClassCastException, не может привести Process к Processor):

public void testPlugins(){

    Processor plugin = (Processor) loadJars("C:\\Users\\...\\Desktop\\processor.jar",
            "C:\\Users\\...\\Desktop\\plugin.jar",
            "test.process.Process");
    processor.loadData("dada");

}

Все еще нужно много читать о загрузке классов, но я предполагаю, что проблема в том, что он не распознает процессор, загруженный из C:\Users\...\Desktop\processor.jar, так же, как процессор, загруженный из контекста webapp или он "забывает", процесс расширяет процессор.

Я спешил, поэтому у меня не было времени на исследования, для решения проблемы я использовал методы с помощью рефлексии:

public void modifiedTestPlugins(){

    Object plugin = loadJar("C:\\Users\\...\\Desktop\\processor.jar",
            "C:\\Users\\...\\Desktop\\plugin.jar",
            "test.process.Process");

    try {
        Method processData = findMethod(obj.getClass(), "processData");

        //here I invoke the processData method, it prints: PROCESS DATAAAAAAAAAAAA
        loadData.invoke(processData, new Object[]{});
    } catch (Exception e) {
        e.printStackTrace();
    }

}

private static Method findMethod(Class clazz, String methodName) throws Exception {
    Method[] methods = clazz.getMethods();
    for (int i = 0; i < methods.length; i++) {
        if (methods[i].getName().equals(methodName))
            return methods[i];
    }
    return null;
}
Другие вопросы по тегам