Ankündigung

Einklappen
Keine Ankündigung bisher.

Rootloader in Groovy Script

Einklappen
X

Rootloader in Groovy Script

Einklappen
  • Filter
  • Zeit
Alles löschen
neue Beiträge

  • l9y2w5
    antwortet
    Hallo tobiz und Martin,
    danke für eure Ideen. Ich bin in dem Thema jetzt weiter gekommen. Musste mein Wissen über ClassLoader erst einmal vertiefen,um zu realisieren, dass das was ich da vorhatte so nicht funktioniert. GroovyShell, wie tobiz ja schon anmerkte, funktioniert am Ende auch nur über reflections wie auch der Rootloader. Darüberhinaus kann der Rootloader nur compilierte .class Klassen laden, nicht aber .groovy files (was ich absolut merkwürdig finde!).

    Nochmal zur Erinnerung, der Use Case ist, dass ich während des developments den Server nicht ständig neu starten kann, da mehrere Personen darauf arbeiten. Dadurch bekomme ich neue Klassen nicht auf den Classpath, da auch die
    Code:
    addURL
    Methode der ClassLoader, mit ausnahme des Rootloaders, immer protected ist. Zusätzlich würde natürlich auch der Classpath mit der Zeit extrem gross, wenn wir für jede Applikation mehrere eigene Klassen auf den Classpath schubsen würden. Daher macht es Sinn zusätzliche Klassen nur im benötigten Scope zu laden. Und das möglichst ohne reflections, da es so convinient wie möglich sein soll. Daher ist die Idee mit Handlern verknüpfte Scripts als Caller-Script für weitere Scripts zu verwenden, diese mit einem eigenen Classloader, der alle abhängigen Klassen läd, in einer GroovyShell auszuführen. Die dort geladenen Klassen können sogar returned oder mittels sharedState an das Caller-Script zurückgegeben werden, wenn der need besteht.

    Code:
    import java.io.File
    import groovy.lang.GroovyClassLoader
    import groovy.lang.GroovyShell;
    import groovy.lang.Script;
    import org.codehaus.groovy.control.CompilerConfiguration;
    import groovy.lang.Binding
    import de.uplanet.lucy.server.scripting.groovy.IxGroovyScript
    import java.io.FileNotFoundException
    
    class DynamicClassLoader extends GroovyClassLoader {
    
    private GroovyShell gs
    private Binding bdg
    /*
    * @constructor
    * @args: none
    *
    * @description: the default constructor is hidden from the user as we hardly need a parent and a binding
    *
    */
    private DynamicClassLoader(){
    
    }
    /*
    * @constructor
    * @args: Classloader parent, Binding binding
    *
    * @description: builds a new DynamicClassloader with a standard IX CompilerConfig
    */
    public DynamicClassLoader( ClassLoader parent, Binding binding ){
    super( parent, DynamicClassLoader.createDefaultIXCompilerConfiguration() )
    this.bdg = binding
    this.addDefaultClassPath()
    }
    
    /*
    * @args: none
    * @return: CompilerConfiguration
    * @see(link)
    *
    * description: returns a custom compiler configuration which forces the encoding to be UTF-8 and the ScriptBaseClass to be of type "IxGroovyScript"
    */
    private static CompilerConfiguration createDefaultIXCompilerConfiguration(){
    CompilerConfiguration ccfg = new CompilerConfiguration()
    ccfg.setSourceEncoding("UTF-8");
    ccfg.setScriptBaseClass(IxGroovyScript.class.getNa me());
    
    return ccfg
    }
    
    /*
    * @args: String appGUID
    * @return: String
    * @description: returns the relative base path of groovy scripts within the application context. Relative means relative to working dir (E:\)
    */
    public static getRelativeAppGroovyBasePath( String appGUID ){
    String basePath = "internal/application/store/" + appGUID + "/groovy/"
    return basePath
    }
    
    /*
    * @args: none
    * @return: none
    * @description: adds the default paths to the classpath
    */
    private void addDefaultClassPath(){
    String parentDirectory = "lib/custom/classes/"
    
    try{
    
    URL classPath = new File( parentDirectory ).toURI().toURL()
    super.addURL( classPath )
    }catch( FileNotFoundException e){
    println e.toString()
    }
    }
    
    /*
    * @args: none
    * @return: none
    * @description: instaciates the objects groovyshell with this object as parent classloader and the binding property as binding
    */
    private void instanciateGroovyShell(){
    super.clearCache()
    this.gs = new GroovyShell( super, this.bdg, DynamicClassLoader.createDefaultIXCompilerConfiguration() )
    }
    
    /*
    * @args: String pathToScript
    * @return: Object
    * @throws: FileNotFoundException
    * @description: runs a script from the current folder
    */
    public Object runIXScript( String pathToScript ) throws FileNotFoundException{
    if( this.gs == null ) instanciateGroovyShell()
    File ixScriptFile = new File( pathToScript )
    this.gs.getClassLoader().clearCache()
    Script script = ( IxGroovyScript ) this.gs.parse( ixScriptFile )
    IxGroovyScript ixScript = ( IxGroovyScript ) script
    Object result = ixScript.run()
    
    return result
    }
    
    /*
    * @args: none
    * @description: Getter for GroovyShell property
    */
    public GroovyShell getGroovyShell(){
    if( this.gs == null ) instanciateGroovyShell()
    return this.gs
    }
    
    public String[] getClassPath(){
    return super.getClassPath()
    }
    
    public Class findClass( String name ){
    return super.findClass( name )
    }
    
    
    }
    Tatsächlich könnte ich mir vorstellen, dass der Aufruf von Handlern und Prozessen ähnlich abläuft. Da wäre es viiiiiieleicht irgendwann ein schönes Feature den zusätzlichen Classpath als Expert Attribut angeben zu können Wäre aber schon ziemlich advanced, weis nicht ob das in eurem Scope liegen kann... möglicherweise gibt es das auch schon in neueren Versionen. Ich arbeite noch auf 18.03.

    Viele Grüße

    Einen Kommentar schreiben:


  • tobiz
    antwortet
    Vielleicht kommst du mit GroovyShell ein wenig weiter?... (auch nur dynamisch)

    Einen Kommentar schreiben:


  • l9y2w5
    antwortet
    Danke für die schnelle Antwort. Ja, ich habe heute auch noch etwas rumprobiert. Ja, ich habe den Rootloader importiert und in eine eigene Klasse gewrappt. Dadurch konnte ich die loadClass Methode public nutzen. Leider lief das insgesamt etwas am Ziel vorbei. Ich hatte erwartet, dass der Groovy Rootloader auch .groovy Dateien, sofern sie Klassen enthalten dynamisch vom Classpath läd. Leider ist dem nicht so. Nur compilierte java Klassen, also .class werden geladen.
    Gibt es einen Weg .groovy files dem Classpath hinzuzufügen? Nicht dynamisch, das funktioniert mit dem GroovyClassLoader, aber allgemein? In der portal.wcf wird das nicht funktionieren, da dort die JVM konfiguriert wird und die Groovy Klassen daher ignoriert.

    Mein Ziel ist es .groovy Dateien in Handler-, globalen Groovy- und Workflowscripts per import einzubinden. Das dynamische laden ist nur ein gimmic fürs development an sich.

    Einen Kommentar schreiben:


  • MartinW
    antwortet
    Nicht alle Klassen werden standardmäßig in die Skripte eingebunden. Hast du versucht den RootLoader mit einem import-Statement einzubinden?
    Inwieweit der RootLoader in Intrexx was kaputt machenkann, kann ich persönlich nicht sagen.

    Das Highlighting im Code bedeutet nicht unbedingt, dass wir den Begriff kennen. Soweit ich weis wird da ein Codeeditor verwendet der von sich aus viele Dinge erkennt und einfärbt.
    Zuletzt geändert von MartinW; 01.03.2021, 08:42.

    Einen Kommentar schreiben:


  • l9y2w5
    hat ein Thema erstellt Rootloader in Groovy Script.

    Rootloader in Groovy Script

    Hallo zusammen,

    neulich habe ich versucht Klassen in Groovy dynamisch mit dem RootLoader zu laden. Dabei ist mir aufgefallen, dass der Groovy RootLoader nicht verfügbar ist. Mit anderen Worten
    Code:
    def cl = this.class.classLoader // returns the current class loader
    def rl = cl.rootLoader // returns null
    Das ist per Definition auch ganz richtig so, wie man auf Stack Overflow lesen kann, da Intrexx Server vermutlich mit Java und nicht mit Groovy ausgeführt wird.

    Trotzdem scheint Intrexx den rootloader zu kennen, da
    Code:
     def rootLoader
    den rootloader blau markiert. Das trifft auch auf manch andere Standards wie .get() zu. Ich hatte es schon fast aufgegeben, aber, dass Intrexx anscheinend weis was rootloader ist schürt in mir die Hoffnung, dass ich den Rootloader des aktuellen scripts doch irgendwie bekommen kann. Gibt es dafür eine Lösung?
Lädt...
X