mstaender
I'm new here

Modulentwicklung (Skripte): Verwendung von Executables vs. Klassen direkt verwenden

Jump to solution

Hi,

in der DTA hatten wir verschiedene Möglichkeiten wie wir unseren Code aufrufen können. Damals klang das stimmig aber nachdem ich jetzt real damit gekämpft habe ergeben sich einige Fragen.

  1. Bei Executables gebe ich in der Modulbeschreibung ein Public-Objekt mit einer "Executable-Schnittstelle" an das also nach außen hin erreichbar ist. Wäre es nicht public, dann könnte das Skript nicht drauf zugreifen. Jetzt meine Fragen hierzu:
    1. Parameter und Rückgabewerte von Executables
      Auf Eingabe-Parameter habe ich schon mal über ein Render-Template -> Skript -> Executable zugegriffen indem ich wilde Konstrukte durchgeführt habe: zuerst erzeuge ich mir eine leeres Array im Template, dann rufe ich ein Renderskript auf und übergebe mein Array zusammen mit anderen Parametern an das Skript und das übergibt die Parameter magisch an die Executable. Nun konnte ich in der Executable drauf zugreifen und Ergebnisse in das Array schreiben die danach im Template in meinem Array zur Verfügung standen.

      Wie übergebe ich denn jetzt Parameter, wenn ich nicht über ein Render-Skript gehe, sondern z.B. das Skript über einen Kontexteintrag starte? Dann würde ich z.B. gerne im Beanshell Skript zunächst irgendwelche Daten über das angeklickte Objekt holen oder sonstwelche Operationen aufrufen, diese dann der Executable zur Verfügung stellen und am Ende mit den Ergebnissen weiterarbeiten (in dem Beanshell Skript). Ist das möglich und sinnvoll?
    2. Einfache Rückgabe bei Executables
      Nachdem ich immer wieder komische Probleme mit obiger Rückgabe-Methode hatte und einfach nur eine Methode aufrufen will (Argumente rein, Operation durchführen, ein Wert (String von mir aus) zurück) die Frage: kann ich in einer Executable einfach einen Wert zurückgeben der entweder im Renderskript ausgegeben wird oder im Beanshell Skript zur Verfügung steht zum bearbeiten?
  2. Momentan löse ich das Problem indem ich direkt auf eine Klasse zugreife und nicht auf einen in der Modulbeschreibung definierten Einstiegspunkt. Damit das Beanshell Skript jedoch die Klasse findet muss ich die resource auf Scope "server" stellen (<resource scope="server">) Resultat: alle Abhängigkeiten müsste ich auf Scope "server" stellen was wirklich schlimm wäre. Sehe ich das falsch oder gibt es hier eine andere Lösung?

Also offenbar fehlt mir hier noch ein klein wenig Verständnis und ich hoffe ich habe mich halbwegs klar ausgedrückt und die Experten hier können mir helfen das ganze zu verstehen Smiley Happy

MfG Marcus

1 Solution

Accepted Solutions
marza
I'm new here

Hallo Marcus,

die Verwendung der Executable ist stark vom jeweiligen Kontext abhängig.

Du hast in der DTA gelernt, dass aus der Map über den Parameter context ein BaseContext zu erhalten ist. Je nach dem, von wo die Executable aufgerufen wird, ist das nicht nur einfach ein BaseContext, sondern ein speziellere Klasse. Im Fall, dass Du die Executable via Script aus dem Kontextmenü aufrufst, ist das z.B. ein ClientScriptContext oder sogar ein GuiScriptContext. Dieser erlaubt Dir mit getElement() direkt auf die Selektion zuzugreifen. Auch bekommst Du unmittelbar Zugriff auf das Projekt mit getProjekt().

Tipp: Wenn Du den BaseContext hast, dann kannst Du über diesen den echten Klassennamen loggen:

context.logInfo(context.getClass().getSimpleName());

Diesen kannst Du dann im API-Doc nachschlagen. Die Information wird in der JConsole ausgegeben oder Du verwendest mein cooles Second-Hand-Log Smiley Wink.

Im Fall, dass Du das Script bzw. die Executable im Template aufrufst, hast Du dann einen GenerationenContext. Rufst Du die Executable im Generierungsauftrag auf, dann hast Du dort den ScheduleContext.

Jetzt zur Ein- bzw. Ausgabe. Die ist ebenfalls stark vom Kontext abhängig. Beim Einsatz im Kontextmenü macht ein Rückgabewert über return keinen Sinn. Hier ist die Executable ein Hook wie in Swing der ActionListener. Bzgl. der Eingabe würde sich im UI-Umfeld vermutlich der FormAgent eignen, der dann auch im ContentCreator funktioniert. Für einfache Ja/Nein-Entscheidungen reicht aber auch der OperationenAgent mit der RequestOperation. Oder m

Beim Einsatz im TemplateCode muss man folgendes machen, wenn man neue Variablen verfügbar machen will:

String myValue = "...";

BaseContext context = (BaseContext) args.get("context");

if (context instanceof GenerationContext) {

    GenerationContext generationContext = (GenerationContext) context;

    generationContext.getPageContext().setVariableValue("myVar", myValue);

}

---------------------------------------

Im Templatecode dann per $CMS_VALUE(myVar)$

Wie die Eingabe hier funktionierst, hast Du bereits erwähnt.

Beim Auftrag gibt es eine UI in der man die Parameter angibt. Weitere Infos hier: http://www.e-spirit.com/odfs52/vorlagenentwicklung/scripting/scripts-erstellen/kontext/client/

Noch ein Tipp: Packe keine Geschäftslogik in Executables, sondern verwende die Executable nur als Hook für die jeweilige Situation bzw. um Ein- bzw. Ausgabe zu managen (Parameter aus der Map holen oder per Dialog vom Benutzer abfragen). Die eigentliche Logik kommt in eine Java-Klasse, welche z.B. im Konstruktor einen BaseContext erwartet. So kann man diese dann in verschiedenen Executable wiederverwenden, sollte das nötig sein. So machen wir das in unseren Modulen auch. Und man kann so auch die Logik viel einfacher in JUnit testen.

Grüße Marian

View solution in original post

3 Replies
marza
I'm new here

Hallo Marcus,

die Verwendung der Executable ist stark vom jeweiligen Kontext abhängig.

Du hast in der DTA gelernt, dass aus der Map über den Parameter context ein BaseContext zu erhalten ist. Je nach dem, von wo die Executable aufgerufen wird, ist das nicht nur einfach ein BaseContext, sondern ein speziellere Klasse. Im Fall, dass Du die Executable via Script aus dem Kontextmenü aufrufst, ist das z.B. ein ClientScriptContext oder sogar ein GuiScriptContext. Dieser erlaubt Dir mit getElement() direkt auf die Selektion zuzugreifen. Auch bekommst Du unmittelbar Zugriff auf das Projekt mit getProjekt().

Tipp: Wenn Du den BaseContext hast, dann kannst Du über diesen den echten Klassennamen loggen:

context.logInfo(context.getClass().getSimpleName());

Diesen kannst Du dann im API-Doc nachschlagen. Die Information wird in der JConsole ausgegeben oder Du verwendest mein cooles Second-Hand-Log Smiley Wink.

Im Fall, dass Du das Script bzw. die Executable im Template aufrufst, hast Du dann einen GenerationenContext. Rufst Du die Executable im Generierungsauftrag auf, dann hast Du dort den ScheduleContext.

Jetzt zur Ein- bzw. Ausgabe. Die ist ebenfalls stark vom Kontext abhängig. Beim Einsatz im Kontextmenü macht ein Rückgabewert über return keinen Sinn. Hier ist die Executable ein Hook wie in Swing der ActionListener. Bzgl. der Eingabe würde sich im UI-Umfeld vermutlich der FormAgent eignen, der dann auch im ContentCreator funktioniert. Für einfache Ja/Nein-Entscheidungen reicht aber auch der OperationenAgent mit der RequestOperation. Oder m

Beim Einsatz im TemplateCode muss man folgendes machen, wenn man neue Variablen verfügbar machen will:

String myValue = "...";

BaseContext context = (BaseContext) args.get("context");

if (context instanceof GenerationContext) {

    GenerationContext generationContext = (GenerationContext) context;

    generationContext.getPageContext().setVariableValue("myVar", myValue);

}

---------------------------------------

Im Templatecode dann per $CMS_VALUE(myVar)$

Wie die Eingabe hier funktionierst, hast Du bereits erwähnt.

Beim Auftrag gibt es eine UI in der man die Parameter angibt. Weitere Infos hier: http://www.e-spirit.com/odfs52/vorlagenentwicklung/scripting/scripts-erstellen/kontext/client/

Noch ein Tipp: Packe keine Geschäftslogik in Executables, sondern verwende die Executable nur als Hook für die jeweilige Situation bzw. um Ein- bzw. Ausgabe zu managen (Parameter aus der Map holen oder per Dialog vom Benutzer abfragen). Die eigentliche Logik kommt in eine Java-Klasse, welche z.B. im Konstruktor einen BaseContext erwartet. So kann man diese dann in verschiedenen Executable wiederverwenden, sollte das nötig sein. So machen wir das in unseren Modulen auch. Und man kann so auch die Logik viel einfacher in JUnit testen.

Grüße Marian

sebastianc
Crownpeak employee

Hallo Marcus,

ist diese Frage noch offen? Benötigst du noch weitere Hilfe oder konnte Marian dir bereits weiterhelfen? In diesem Fall wäre es super, wenn du seine "richtige Antwort" entsprechend markierst.

Viele Grüße,

Sebastian

0 Kudos

Hi Sebastian,

ich muss das noch durcharbeiten aber ich denke die Frage ist beantwortet. Danke euch.

MfG Marcus

0 Kudos