Интеграция стороннего API в приложение Java с конфликтующими зависимостями - PullRequest
3 голосов
/ 05 марта 2011

Я работаю над существующим приложением, которое имеет довольно много внешних JAR-зависимостей.Мне нужно улучшить его для интеграции со сторонним приложением, которое имеет API.К сожалению, API не очень хорошо содержится, а также имеет большое количество собственных зависимостей, некоторые из которых конфликтуют с моей.

Я считаю, что должен решить эту проблему с помощью Classloaders, но я изо всех сил пытаюсь понять, какструктурируйте их правильно.

Для простоты предположим, что у нас есть myapp.jar с зависимостью hibernate3.jar, а vendor-api.jar с зависимостью hibernate2.jar (и предположим, что они несовместимы).

Мой новый кусок кода будет находиться в библиотеке myapp.jar (хотя это может быть в отдельном jar, если это поможет).Из-за того, как работает API вендора, мой новый код должен расширять класс из библиотеки vendor-api.jar.

Как я могу структурировать загрузчики классов таким образом, чтобы что-либо внутри vendor-api.jar обращалось только к своим собственным зависимостям, а все, что на моей стороне, получало доступ только к myapp.jar и зависимостям?

Спасибо, Джон

Ответы [ 3 ]

1 голос
/ 05 марта 2011

Я не пробовал это сам, но по памяти каждый конфликтующий класс должен находиться в загрузчике классов-братьев, и любая связь между ними должна проходить через общего предка. Однако предок не может (AFAIK) «напрямую» ссылаться на классы своих дочерних элементов и должен обращаться к ним через API отражения.

Что-то в этом духе должно работать (с сухим кодом) YMMV. Комментарии и сообщения об ошибках приветствуются.

class Orchestrator {
    URL[] otherAppClasspath = new URL[] { new URL("file:///vendor-api.jar"),
                                          new URL("file:///hibernate2.jar"),
                                          new URL("file:///code-extending-vendor-api.jar" };
    URLClassLoader otherAppLoader = new URLClassLoader(otherAppClasspath);

    URL[] yourAppClasspath = new URL[] { new URL("file:///myapp.jar"),
                                         new URL("file:///hibernate3.jar") };
    URLClassLoader yourAppLoader = new URLClassLoader(yourAppClasspath);

    public void start() {
        Method yourAppEntryPoint = yourAppLoader.findClass("com/company/Main").getMethod("start", new Class[] { Orchestrator.class } );
        yourAppEntryPoint.invoke(null, new Object[] { this });
    }

    public static void main(String[] args) {
        new Orchestrator().start();
    }

    // define some abstracted API here that can be called from your app
    // and calls down into classes in the other app
    public String getSomeResultFromOtherApp(int someArgument) {
        Method otherAppAPI = otherAppLoader.findClass("com/company/ExtendingAPIClass").getMethod("getSomeResult", new Class[] { Integer.class });
        return (String)otherAppAPI.invoke(null, new Object[] { someArgument });          
    }

}
0 голосов
/ 05 марта 2011

Использование OSGi может помочь вам в долгосрочной перспективе. Вот реализация, которую я сейчас пробую - http://felix.apache.org

0 голосов
/ 05 марта 2011

@ fd ответ дает технический механизм, который должен работать - давать или принимать некоторые опечатки, обработку исключений и т. Д.

Тем не менее, я думаю, что вам было бы лучше не пытаться делать это ... если только ваши зависимости от сторонних API не ограничены очень небольшим количеством методов в очень небольшом количестве классов. Каждый класс, от которого вы зависите, должен быть динамически загружен, и каждый метод должен быть найден и вызван рефлексивно. Слишком много, и ваша кодовая база пострадает.

На вашем месте я бы попытался решить проблему зависимости другим способом:

  1. Попробуйте заставить стороннего поставщика использовать hibernate3.jar
  2. Измените ваше приложение на использование hibernate2.jar
  3. Выполните рефакторинг, чтобы код приложения и сторонняя библиотека находились в отдельных JVM или в отдельных веб-приложениях.

Из того, что вы говорите, это может быть трудно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...