JBoss 7: как динамически загружать банки - PullRequest
11 голосов
/ 03 января 2012

Я использую JBoss 7 (загрузка зависимостей была изменена в этой версии). Мое war-приложение загружает на серверные jar-файлы и требует использования классов внутри них, но оно получает ClassNotFoundException. Поэтому я не могу найти способ динамического добавления jar-зависимостей в модули - MANIFEST.MF, jboss-deployment-structure.xml - статический способ сделать это.

Ответы [ 3 ]

5 голосов
/ 02 января 2013

Просто перефразирую вопрос, чтобы убедиться, что я правильно его понимаю;

Вы хотите иметь возможность загрузить произвольный файл JAR на сервер, а затем использовать содержащиеся в JVM классы / ресурсы? Без перезапуска JVM и / или редактирования вашей конфигурации курса.

Если это так, то вам следует загрузить jar в загрузчик классов (при необходимости, цепочку вашего текущего загрузчика классов), а затем загрузить класс оттуда.

Предполагая, что вы храните jar-файл физически на сервере, вы можете, например, сделать что-то вроде:

public static Class<?> loadClass(String className, String jarFileLocation)
        throws MalformedURLException, ClassNotFoundException {
    URL jarUrl = new File(jarFileLocation).toURI().toURL();
    ClassLoader classLoader = new URLClassLoader(new URL[] {jarUrl }, MyClass.class.getClassLoader());
    return classLoader.loadClass(className);
}

public static Object executeMethodOndClass(String methodName, Class<?>[] parameterTypes, 
                                                Object[] parameters, String className, String jarFileLocation)
        throws MalformedURLException, ClassNotFoundException, IllegalAccessException, InstantiationException,
        NoSuchMethodException, InvocationTargetException {
    Class<?> loadedClass = loadClass(className, jarFileLocation);
    Method method = loadedClass.getMethod(methodName, parameterTypes);
    Object instance = loadedClass.newInstance();
    return method.invoke(instance, parameters);
}

Ps. это грубый код, я даже не компилировал и не тестировал его; это должно работать, но не более того, и есть шанс, что я что-то упустил или сделал опечатку; -)

Pps. разрешение загрузки пользовательских jar-файлов и выполнение классов из них сопряжено с рядом рисков для безопасности.

0 голосов
/ 09 января 2013

Попробуйте это (я взял это где-то в Интернете):

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public final class ClassPathHacker {
    private static final Class<?>[] PARAMS = new Class<?>[] { URL.class };
    private static final Logger LOG_CPH = LoggerFactory.getLogger(ClassPathHacker.class);

    private ClassPathHacker() {}

    public static void addFile(final String pFileName) throws IOException {
        final File myFile = new File(pFileName);

        ClassPathHacker.addFile(myFile);
    }

    public static void addFile(final File pFile) throws IOException {
        ClassPathHacker.addURL(pFile.toURI().toURL());
    }

    public static void addURL(final URL pFileUrl) throws IOException {

        /* variables definition */
        final URLClassLoader sysLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
        final Class<?> sysClass = URLClassLoader.class;

        try {
            final Method myMethod = sysClass.getDeclaredMethod("addURL", PARAMS);

            myMethod.setAccessible(true);
            myMethod.invoke(sysLoader, new Object[] { pFileUrl });
        } catch (final Exception exc) {
            ClassPathHacker.LOG_CPH.error(exc.getLocalizedMessage(), exc);

            throw new IOException(exc.getLocalizedMessage());
        }
    }
}

Вместе с этим методом:

private static void hackClassPath(final File myData) {
    if (myData.isDirectory()) {

        /* block variables */
        final File[] myList = myData.listFiles();

        /* hacking classpath... */
        for (final File tmp : myList) {
            try {
                ClassPathHacker.addFile(tmp.getAbsolutePath());
                MainApplication.MAIN_LOG.trace("{} added to classpath",
                                               tmp.getAbsolutePath());
            } catch (final IOException iOE) {
                MainApplication.MAIN_LOG.error(iOE.getLocalizedMessage(),
                                               iOE);
            }
        }
    }
}

И с этим примером вызова:

    MainApplication.hackClassPath(new File("test/data"));
    MainApplication.hackClassPath(new File("data"));

Немного странно, но, возможно, это работает ... во время выполнения все файлы JAr, доступные в каталоге data или test / data, добавляются в текущий путь к классу.

0 голосов
/ 09 января 2013

@ Rage: Этот вопрос о стековом потоке, заданный ранее, может дать вам некоторые сведения о том, как организовать jar: будь то ваши собственные или сторонние jar.

...