Как сделать динамически загружаемый плагин осведомленным о веб-приложении

Я решил реализовать динамическую загрузку классов в моем веб-приложении Glassfish, чтобы испытать его и поддерживать небольшие плагины, которые могут загружаться и выполняться веб-приложением во время выполнения.

Я добавил следующий класс:

public class PluginManager {

   private static final String dropBoxDir = "file:///path/to/dropbox/";
   private static final URLClassLoader dropBoxClassLoader;
   static {
      try {
         URL dropBoxURL = new URL(dropBoxDir);
         dropBoxClassLoader = URLClassLoader.newInstance(new URL[]{dropBoxURL});
      }
      catch (MalformedURLException mue) {
         throw new RuntimeException("MalformedURLException thrown during PluginManager initialization - the hardcoded URL " + dropBoxDir + " must be invalid.", mue);
      }
   }

   //this method is called by a web service
   public static void runPluginFromDropBox(String fullClassName) {
      try {
         //load the plugin class
         Class<?> pluginClass = dropBoxClassLoader.loadClass(fullClassName);
         //instantiate it
         Runnable plugin = (Runnable)pluginClass.newInstance();
         //call its run() method
         plugin.run();
      }
      catch (ClassNotFoundException cnfe) {
         throw new RuntimeException("The class file for " + fullClassName + " could not be located at the designated directory (" + dropBoxDir + "). Check that the specified class name is correct, and that its file is in the right location.", cnfe);
      }
      catch (InstantiationException ie) {
         throw new RuntimeException("InstantiationException thrown when attempting to instantiate the plugin class " + fullClassName + " - make sure it is an instantiable class with a no-arg constructor.", ie);
      }
      catch (IllegalAccessException iae) {
         throw new RuntimeException("IllegalAccessException thrown when attempting to instantiate the plugin class " + fullClassName + " - make sure the class and its no-arg constructor have public access.", iae);
      }
      catch (ClassCastException cce) {
         throw new RuntimeException("Plugin instance could not be cast to Runnable - plugin classes must implement this interface.", cce);
      }
   }
}

Затем в отдельном проекте я создал тестовый плагин:

public class TestPlugin implements Runnable {
   @Override
   public void run() {
      System.out.println("plugin code executed");
   }
}

Я развернул веб-приложение, затем скомпилировал TestPlugin в .class файл и поместил его в назначенную папку. Я позвонил в веб-сервис, который ударил runPluginFromDropBox() с именем класса и получил ожидаемый результат.

Все это работало как подтверждение концепции, но мой плагин практически бесполезен, если его не узнать о классах моего веб-приложения. С тех пор я прочитал это .war предназначено только как отдельное приложение и не предназначено для пути к классам других библиотек, что не сулит ничего хорошего для этого небольшого побочного проекта.

Я взглянул на эту дискуссию: расширение веб-приложений Java с помощью плагинов и ощущение, что я без особых на то оснований сталкиваюсь с множеством проблем проектирования и должен обернуться. Однако этот пост довольно старый и специфичен для Tomcat, поэтому я просто подумал, что могу спросить, есть ли какой-нибудь прямой способ подойти к этому без какой-либо сложной сторонней структуры.

1 ответ

Решение

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

Чтобы знать о классах webapp, ваш загрузчик классов плагина должен иметь загрузчик классов webapp в качестве родителя. Я не знаю всех проблем, которые могут возникнуть при использовании дополнительного загрузчика классов, но я подозреваю, что у вас могут возникнуть утечки памяти и другие неприятные проблемы (статические значения, сохраняемые в памяти и т. Д.), Когда контейнер будет развернут и повторно развернут веб-приложение. И у вас могут быть различия между контейнерами.

Другие вопросы по тегам