2016-04-21 11 views
0

ich angelegt habe zwei groovy Erweiterungsmodule/Methoden auf java.util.ArrayList(). Es funktioniert alles sehr gut in meiner IDE. Ich benutze gradle das Glas zu bauen, und stellen Sie sie an einen entfernten JVM. Wenn es die entfernte JVM erreicht, schlägt es fehl.Groovy Extension Module Methode - Keine Unterschrift Methode

Hier ist die Extension-Methode:

static Map sumSelectedAttributes(final List self, List attributes) { 
    Map resultsMap = [:] 
    attributes.each { attr -> 
     resultsMap[attr] = self.inject(0) { sum, obj -> 
      sum + obj[attr] 
     } 
    } 
    return resultsMap 

Hier ist der Code, der sie aufruft:

outputMap[processName][iName] << kBeanList.sumSelectedAttributes([ 
    "messageCount", "userCount", "outstandingRequests", 
    "cpuUsage", "memoryUsage", "threadCount", "cacheCount", "huserCount", 
    "manualHuserCount", "dataPointerCount", "tableHandleCount", 
    "jdbCacheRecordCount", "dbConnectionCount"]) 

Hier ist der Fehler:

No signature of method: java.util.ArrayList.sumSelectedAttributes() is applicable for argument types: (java.util.ArrayList) values: [[messageCount, incomingConnectionsCount, outgoingConnectionsCount, ...]]

Auch hier funktioniert es gut in intellij mit Testfällen. Was ist auf der Remote-JVM anders, um dies zu verhindern? Hier sind einige Dinge, die mir in dem Sinn kamen:

  1. Das Remote-JVM verwendet Groovy 2.3 während ich auf 2.4.5
  2. Wir verwenden einen benutzerdefinierten Classloader auf der Remote-JVM-Klassen zu laden

Darüber hinaus konnte ich keine andere Dokumentation zu etwas Besonderem finden, das ich tun muss, damit Erweiterungen auf Remote-JVMs funktionieren.

Jede Hilfe wird sehr geschätzt.

Pro einen Kommentar, scheint wie ein Problem mit benutzerdefinierten Klassenlader, hier ist die Klasse, die die Manipulation von einigen Klassenladeprogrammen behandelt.

class CustomLoader { 
    static Map loaders = [:] 
    static File loaderRoot = new File("../branches") 

    static URLClassLoader getCustomLoader(String branchName) { 
     if (!loaders[branchName]) { 
      loaders[branchName] = new URLClassLoader(getUrls(branchName)) 
     } else { 
      loaders[branchName] 
     } 
    } 

    static URLClassLoader updateClassLoader(String branchName) { 
     loaders[branchName] = null 
     loaders[branchName] = new URLClassLoader(getUrls(branchName)) 
    } 

    private static URL[] getUrls(String branchName) { 
     def loaderDir = new File(loaderRoot, branchName) 
     List<File> files = [] 
     loaderDir.eachFileRecurse{ 
      if (it.name.endsWith('.jar')) { 
       files << it 
      } 
     } 
     List urls = files.sort{ it.name }.reverse().collect{it.toURI().toURL()} 
     return urls 
    } 
} 
+0

Wenn Sie benutzerdefinierten Class Loader sagen, klingelt es die Alarme;) Generell für Groovy der Lage sein, ein Erweiterungsmodul zu laden, muss dieses Modul an den Loader der Groovy Laufzeit sichtbar. Das unterscheidet sich von der Art, wie Ihre Anwendung normalerweise funktioniert, da der Anwendungsklassenlader die Laufzeit anzeigen muss, die Laufzeit jedoch nicht die Anwendungsklassen anzeigt. Natürlich frage ich mich jetzt, wie Sie das Setup für die Klasseninstallation auf der Remote-JVM installieren. – blackdrag

+0

Vielen Dank für Ihre Antwort, und es klingt, als hätten Sie das Problem sofort erkannt. In diesem Fall ist es einfach unmöglich, Erweiterungsmodule zu verwenden. Können Sie basierend auf meinem Code einen alternativen Ansatz empfehlen? Ich habe irgendwie viel Code geplant. Nur zur Bestätigung, und für die Nachwelt, habe ich gerade die "classloader class" zum ursprünglichen Post für Ihre Rezension hinzugefügt.Es ist in einer Entwicklungsumgebung, wo wir verschiedene Versionen von Gläsern gleichzeitig laden müssen, und Änderungen flexibel laden müssen, ohne JVM neu zu starten. (Dev/Test/Produktzweige). – solvingJ

Antwort

1

Um ein Erweiterungsmethode-Modul manuell zu registrieren, können Sie einen ähnlichen Code wie in GrapeIvy verwenden. Weil Weintrauben das gleiche Problem haben, indem sie ein Glas im falschen Loader sichtbar machen, aber trotzdem Erweiterungsmethoden aktivieren wollen. Das Stück Code in Frage ist hier:

JarFile jar = new JarFile(file) 
def entry = jar.getEntry(ExtensionModuleScanner.MODULE_META_INF_FILE) 
if (entry) { 
    Properties props = new Properties() 
    props.load(jar.getInputStream(entry)) 
    Map<CachedClass, List<MetaMethod>> metaMethods = new HashMap<CachedClass, List<MetaMethod>>() 
    mcRegistry.registerExtensionModuleFromProperties(props, loader, metaMethods) 
    // add old methods to the map 
    metaMethods.each { CachedClass c, List<MetaMethod> methods -> 
    // GROOVY-5543: if a module was loaded using grab, there are chances that subclasses 
    // have their own ClassInfo, and we must change them as well! 
    Set<CachedClass> classesToBeUpdated = [c] 
    ClassInfo.onAllClassInfo { ClassInfo info -> 
     if (c.theClass.isAssignableFrom(info.cachedClass.theClass)) { 
     classesToBeUpdated << info.cachedClass 
     } 
    } 
    classesToBeUpdated*.addNewMopMethods(methods) 
    } 
} 

In dieser Codedatei ist eine Datei, die das Glas darstellt. In Ihrem Fall müssen Sie hier etwas anderes haben. Grundsätzlich wir zuerst die Deskriptordatei in Eigenschaften laden, registerExtensionModuleFromProperties rufen Sie die Karte mit MetaMethods zu füllen auf einem bestimmten Class Loader abhängig. Und das ist der Schlüssel für die Lösung Ihres Problems, der richtige Klassenlader ist hier einer, der alle Klassen in Ihrem Erweiterungsmodul und die groovige Laufzeit laden kann. Danach wird jede neue Meta-Klasse über die Erweiterungsmethoden Bescheid wissen. Der folgende Code wird nur benötigt, wenn bereits Metaklassen vorhanden sind, die Sie über diese neuen Methoden wissen möchten.

+0

Wow, ich glaubte nicht, dass es dafür eine Lösung geben würde. Ich schätze den Einblick und die Informationen sehr! Zu Ihrer Information, weil die Unterstützung durch andere ein ziemlich großer Faktor ist, entschied ich, dass es einfacher wäre, die Funktionen zu einem Merkmal zu machen, und das einfach umzusetzen, wo auch immer ich es brauche. Es dauerte ganze 20 Minuten ... Die Power und Flexibilität von groovy! – solvingJ

Verwandte Themen