2012-01-03 26 views
11

Używam JBoss 7 (ładowanie zależności zostało zmienione w tej wersji). Moja aplikacja wojenna ładuje się do słoików serwerów i musi korzystać z klas wewnątrz nich, ale dostaje ClassNotFoundException. Tak więc nie mogę znaleźć sposobu na dynamiczne dodawanie zależności słoików do modułów - MANIFEST.MF, jboss-deployment-structure.xml to statyczny sposób robienia tego.JBoss 7: jak dynamicznie ładować słoiki

+1

Wspomniał Pan, że załadowanie zależności zostało zmienione dla JBoss 7. Czy zrobiłeś to używając wcześniejszych wersji JBoss? Czy możesz opisać swoje poprzednie podejście? – GargantuChet

+0

Podejrzewam, że [ta dokumentacja] (https://community.jboss.org/wiki/ModuleCompatibleClassloadingGuide) może być pomocna. – higuaro

Odpowiedz

5

Wystarczy przeformułować pytanie, aby upewnić się, czy poprawnie;

Chcesz mieć możliwość przesłania dowolnego pliku JAR na serwer, a następnie użyć zawartych klas/zasobów w JVM? Bez restartowania maszyny JVM i/lub edycji konfiguracji pliku.

W takim przypadku należy załadować słoik do modułu ładującego klasy (w razie potrzeby łańcuchowego do aktualnego programu ładującego klasy), a następnie załadować klasę.

Zakładając zapisać plik JAR fizycznie na serwerze można na przykład zrobić coś takiego:

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. to jest surowy kod, nawet go nie skompilowałem ani nie przetestowałem; to powinno być powinno być pracy, ale nic więcej niż to i jest szansa, że ​​coś przeoczyłem lub zrobiłem literówkę ;-)

Pps. zezwalanie na wysyłanie niestandardowych plików jar i wykonywanie z nich klas niesie ze sobą szereg (bezpieczeństwa) zagrożeń.

+0

Podoba mi się ta odpowiedź, ale nie jest to odpowiedź na pytanie. Ostatecznie różnica między ustawieniem zależności w jboss przez manfiest/jboss-deployment-structure.xml polega na tym, że niejawnie tworzy wszystkie klasy, które są zależne od dostępnych w programie ładującym klasy aplikacji, bez konieczności jawnego nadawania im nazw lub klasowania osobno. Ma to tę zaletę, że zagwarantuje, że wszystkie systemy BlackBox, które przekażesz kontrolerowi (wysyłającemu do sterownika jsp itd.) Również będą miały dostęp do tych klas (jeśli są uruchomione z tym samym modułem ładowania aplikacji). – Rhys

0

@Rage: This question na pytanie stackoverflow może dać kilka informacji, jak zorganizować słoiki: czy to słoiki własne lub strony trzeciej.

0

Spróbuj tego (mam chwycił go gdzieś w internecie):

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()); 
     } 
    } 
} 

Wraz z tą metodą:

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); 
      } 
     } 
    } 
} 

I z tego zaproszenia próbki:

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

Trochę ohydne, ale może działa ... to środowisko wykonawcze dodaje wszystkie pliki JAr dostępne w katalogu danych lub test/data do uruchomionego cl asspath.

Powiązane problemy