Search the FirstSpirit Knowledge Base
Hallo zusammen,
folgendes Problem. Ich möchte eine Executable-Class aus einem Script aufrufen jedoch die übergebene Map vorher noch überarbeiten. Ich hab dazu bereits hier in der Community gesucht und Lösungen gefunden, jedoch hab ich noch ein Problem damit.
wenn ich den "normalen Weg" verwende kann die Executable Class ausgeführt werden und es gibt kein Problem.
#!executable-class
com.test.firstspirit.workflows.release.WfFindRelatedObjectsExecutable
Will ich nun aber die selber Executable Class als Instanz aufrufen, damit ich der Funktion die überarbeitete Map übergeben kann, bekomme ich den Fehler das die Class nicht gefunden wird.
//!Beanshell
import com.test.firstspirit.workflows.release.WfFindRelatedObjectsExecutable;
Map map = new HashMap();
importObject( map );
put("context", context);
put("script", "wf_collect_related_objects");
new WfFindRelatedObjectsExecutable().execute(map);
Fehler der geworfen wird.
WARN 21.01.2016 16:22:30.603 (de.espirit.firstspirit.client.action.WorkflowAction): Error creating task - de.espirit.firstspirit.access.script.ExecutionException: Unknown class: WfFindRelatedObjectsExecutable : at Line: 9 : in file: inline evaluation of: ``__execute() { //!Beanshell import com.test.firstspirit.workflows.release.WfFindRe . . . '' : new WfFindRelatedObjectsExecutable ( )
Called from method: __execute at line 9
FSVersion=5.2.212.71463#3255;JDK=1.8.0_60 64bit Oracle Corporation;OS=Windows 7 6.1 amd64;Date=21.01.2016 16:22:30
de.espirit.firstspirit.access.script.ExecutionException: Unknown class: WfFindRelatedObjectsExecutable : at Line: 9 : in file: inline evaluation of: ``__execute() { //!Beanshell import com.test.firstspirit.workflows.release.WfFindRe . . . '' : new WfFindRelatedObjectsExecutable ( )
Called from method: __execute at line 9
at de.espirit.firstspirit.server.script.BeanshellScriptEngine$BeanshellExecutable.execute(BeanshellScriptEngine.java:111)
at de.espirit.firstspirit.server.script.BeanshellScriptEngine$BeanshellExecutable.execute(BeanshellScriptEngine.java:84)
at de.espirit.firstspirit.client.gui.applications.ApplicationTabRegistry$IdentifiableExecutable.execute(ApplicationTabRegistry.java:104)
at de.espirit.firstspirit.server.taskmanagement.TaskImpl.doTransition(TaskImpl.java:1147)
at de.espirit.firstspirit.server.taskmanagement.TaskImpl.doAutomaticActivities(TaskImpl.java:1602)
at de.espirit.firstspirit.server.taskmanagement.TaskImpl.doTransition(TaskImpl.java:1217)
at de.espirit.firstspirit.server.taskmanagement.TaskImpl.doTransition(TaskImpl.java:1084)
at de.espirit.firstspirit.client.action.WorkflowAction.startWorkflow(WorkflowAction.java:494)
at de.espirit.firstspirit.client.action.WorkflowAction.startWorkflow(WorkflowAction.java:108)
at de.espirit.firstspirit.client.action.WorkflowAction.startWorkflow(WorkflowAction.java:118)
at de.espirit.firstspirit.client.action.WorkflowUtil.startWorkflow(WorkflowUtil.java:65)
at de.espirit.firstspirit.client.action.WorkflowMenuAction$WFStartAction.actionPerformed(WorkflowMenuAction.java:269)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at de.espirit.firstspirit.client.AWTDispatchingEventQueue.defaultDispatchEvent(AWTDispatchingEventQueue.java:161)
at de.espirit.firstspirit.client.AWTDispatchingEventQueue._dispatchEvent(AWTDispatchingEventQueue.java:138)
at de.espirit.firstspirit.client.AWTDispatchingEventQueue.dispatchEvent(AWTDispatchingEventQueue.java:131)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Caused by: bsh.EvalError: Unknown class: WfFindRelatedObjectsExecutable : at Line: 9 : in file: inline evaluation of: ``__execute() { //!Beanshell import com.test.firstspirit.workflows.release.WfFindRe . . . '' : new WfFindRelatedObjectsExecutable ( )
Called from method: __execute
at bsh.BSHAllocationExpression.objectAllocation(BSHAllocationExpression.java:98)
at bsh.BSHAllocationExpression.eval(BSHAllocationExpression.java:62)
at bsh.BSHPrimaryExpression.eval(BSHPrimaryExpression.java:102)
at bsh.BSHPrimaryExpression.eval(BSHPrimaryExpression.java:47)
at bsh.BSHBlock.evalBlock(BSHBlock.java:130)
at bsh.BSHBlock.eval(BSHBlock.java:80)
at bsh.BshMethod.invokeImpl(BshMethod.java:371)
at bsh.BshMethod.invoke(BshMethod.java:267)
at bsh.BshMethod.invoke(BshMethod.java:170)
at bsh.PreparsedScript.invoke(PreparsedScript.java:66)
at de.espirit.firstspirit.server.script.BeanshellScriptEngine$BeanshellExecutable.execute(BeanshellScriptEngine.java:100)
... 52 more
Das Script wird über einen Workflow aufgerufen, falls das eine Rolle spielen sollte und ich verwende die FS Version 5.2
Vielen Dank schon mal!
Dominik
Hallo Dominik,
man muss hier zwischen der <public>-Komponente und ihren Resourcen (=Klassen) unterscheiden. Die Komponente ist sichtbar, obwohl ihre Klassen weiterhin im Module-Scope liegen. Dann muss man bei "manuellem" Zugriff aber auch diesen Mechanismus benutzen.
Das "Entwicklerhandbuch für Komponenten" meint dazu in Kapitel "2.9.1.7 Public":
Ausführbare Klassen: Ressourcen, die als Public-Komponente im Deskriptor eingebunden werden, können ausführbare Implementierungen enthalten. Nach der Installation des Moduls stehen diese ausführbaren Implementierungen auf dem FirstSpirit-Server zur Verfügung und können beispielsweise innerhalb eines Skripts (Auftrags-Skripte im FirstSpirit-Server oder Skripte im FirstSpirit SiteArchitect) aufgerufen werden. Um einen globalen Zugriff auf diese Dateien zu gewährleisten, musste für diese Ressourcen bisher (bis FirstSpirit Version 4.2R4/Build 4.2.434) ein serverweiter Gültigkeitsbereich definiert werden. Das ist nicht in allen Fällen erwünscht. Da beispielsweise Klassen aus global-definierten Jars keine Klassen aus modul-lokal definierten Jars verwenden können, mussten auch alle weiteren Ressourcen mit serverweitem Gültigkeitsbereich definiert werden (vgl. Gültigkeitsbereich von Ressourcen in Kapitel 2.5.1.2).
Ab FirstSpirit Version 4.2R4 (Build 4.2.434) kann eine ausführbare Implementierung auch dann referenziert werden, wenn die Klasse in einem modullokalen Jar-Archiv liegt. Um Konflikte zu vermeiden, sollten alle Ressourcen (JarArchive), soweit das möglich ist, modul-lokal definiert werden.
Darunter ist auch ein Beispiel hierfür mit module.xml und einem Script, das #!executable-class nutzt:
Beispiel (Ressourcen werden mit modul-lokalem Gültigkeitsbereich definiert):
<module>
<name>Modul 1</name>
<version>1.0</version>
<components>
<public>
<name>AppExecutor-Name</name>
<class>de.espirit.pm.modules.modul.AppExecutor</class>
</public>
</components>
<resources>
<resource scope='module'>lib/modul1.jar</resource>
<resource scope='module'>lib/jtwitter_api.jar</resource>
</resources>
</module>
Referenzierung der ausführbaren Klasse im Skript-Source-Tab:
#!executable-class
AppExecutor-Name
//this calls class de.espirit.pm.modules.modul.AppExecutor registered in
//"Module 1"
Viele Grüße
Michael
Hallo Dominik,
ich vermute mal, dass Du die entsprechenden Klassen (=jars) in der module.xml als modul-lokal deklariert hast - was auch so empfohlen wird.
Das führt dann allerdings dazu, dass diese Klassen in Beanshell-Skripten nicht gefunden werden, da diese nur Zugriff auf Server-globale resourcen haben.
Was Du mal versuchen könntest:
Falls noch nicht vorhanden, ein Script definieren, in dem die Klasse als executable-class benutzt wird:
#!executable-class
com.test.firstspirit.workflows.release.WfFindRelatedObjectsExecutable
Wobei es hier übrigens besser ist, keinen FQCN zu nehmen sondern den Namen der entsprechenden <PUBLIC>-Komponente (dann kann man z.B. gefahrloser refactoren) - also z.B. ein Script "find_related_objects_executable" mit
#!executable-class
WfFindRelatedObjectsExecutable
Und dazu passend die Deklaration in der module.xml:
...
<public>
<name>WfFindRelatedObjectsExecutable</name>
<class>com.test.firstspirit.workflows.release.WfFindRelatedObjectsExecutable</class>
</public>
Im Script, das die Executable dann parametrisiert aufrufen soll, zuerst dieses Script-Objekt z.B. per StoreElementAgent holen und dann die Executable nicht instanziieren sondern aus dem Script holen:
Script script = context.requireSpecialist(StoreElementAgent.TYPE)
.loadStoreElement("find_related_objects_executable", Script.UID_TYPE, false);
Executable executable = script.getExecutable(context.getProject().getTemplateSets().get(0));
executable.execute(map);
Viele Grüße
Michael
Hallo Michael,
danke für deine Hilfe. Die Klassen waren bereits als public in der Module.xml deklariert, weshalb es eben auch so komisch ist das er sie nicht findet. Allerdings konnte ich sie jetzt zumindest über deinen Weg mit dem StoreElementeAgent ermitteln und so weiter arbeiten.
Danke und Gruß
Dominik
Hallo Dominik,
man muss hier zwischen der <public>-Komponente und ihren Resourcen (=Klassen) unterscheiden. Die Komponente ist sichtbar, obwohl ihre Klassen weiterhin im Module-Scope liegen. Dann muss man bei "manuellem" Zugriff aber auch diesen Mechanismus benutzen.
Das "Entwicklerhandbuch für Komponenten" meint dazu in Kapitel "2.9.1.7 Public":
Ausführbare Klassen: Ressourcen, die als Public-Komponente im Deskriptor eingebunden werden, können ausführbare Implementierungen enthalten. Nach der Installation des Moduls stehen diese ausführbaren Implementierungen auf dem FirstSpirit-Server zur Verfügung und können beispielsweise innerhalb eines Skripts (Auftrags-Skripte im FirstSpirit-Server oder Skripte im FirstSpirit SiteArchitect) aufgerufen werden. Um einen globalen Zugriff auf diese Dateien zu gewährleisten, musste für diese Ressourcen bisher (bis FirstSpirit Version 4.2R4/Build 4.2.434) ein serverweiter Gültigkeitsbereich definiert werden. Das ist nicht in allen Fällen erwünscht. Da beispielsweise Klassen aus global-definierten Jars keine Klassen aus modul-lokal definierten Jars verwenden können, mussten auch alle weiteren Ressourcen mit serverweitem Gültigkeitsbereich definiert werden (vgl. Gültigkeitsbereich von Ressourcen in Kapitel 2.5.1.2).
Ab FirstSpirit Version 4.2R4 (Build 4.2.434) kann eine ausführbare Implementierung auch dann referenziert werden, wenn die Klasse in einem modullokalen Jar-Archiv liegt. Um Konflikte zu vermeiden, sollten alle Ressourcen (JarArchive), soweit das möglich ist, modul-lokal definiert werden.
Darunter ist auch ein Beispiel hierfür mit module.xml und einem Script, das #!executable-class nutzt:
Beispiel (Ressourcen werden mit modul-lokalem Gültigkeitsbereich definiert):
<module>
<name>Modul 1</name>
<version>1.0</version>
<components>
<public>
<name>AppExecutor-Name</name>
<class>de.espirit.pm.modules.modul.AppExecutor</class>
</public>
</components>
<resources>
<resource scope='module'>lib/modul1.jar</resource>
<resource scope='module'>lib/jtwitter_api.jar</resource>
</resources>
</module>
Referenzierung der ausführbaren Klasse im Skript-Source-Tab:
#!executable-class
AppExecutor-Name
//this calls class de.espirit.pm.modules.modul.AppExecutor registered in
//"Module 1"
Viele Grüße
Michael
Hallo Michael,
das Module spielte die Klassen aber auch bereits mit dem Scope Server aus.
<resource scope="server">lib/zf.workflowsFSM.jar</resource>
Gruß
Dominik
Hallo Michael,
mir ist gerade aufgefallen das in der Module.xml ein Buchstabendreher im schließen Tag von </resources> existierte. Somit wäre das Mysterium warum die Klasse nicht gefunden wurde auch gelöst.
Dankte trotzdem für deine Hilfe.
Gruß
Dominik
Hallo Dominik,
gerne 🙂
Wobei wie gesagt die Modul-lokale Variante immer vorzuziehen ist.
Viele Grüße
Michael