mstaender
I'm new here

ClassNotFoundException im SiteArchitect

Jump to solution

Hi,

ich wollte nach einer etwas längeren Pause nun an meinem Projekt weitermachen und habe gleich zu Beginn festgestellt, dass das Modul im SA (mehr habe ich noch gar nicht getestet) Klassen aus Bibliotheken nicht finden kann die definitiv da sein sollten. Wenn ich den SA aus meiner IDE heraus mit dem Modul starte funktioniert alles einwandfrei, wenn ich ihn jedoch über die Weboberfläche starte, dann tauchen die Fehler auf. Ich habe gestern auf die aktuellste FS Version upgedated aber leider keine Änderung.

Ich habe Menüeinträge die ich verwende um Aktionen durchzuführen, aber auch wenn ich die Executables in einem Skript aufrufe kommt ein ClassNotFound Fehler.

Die gesamte und unzensierte module.xml:

<?xml version="1.0" encoding="UTF-8"?>
<module>

   <name>${project.artifactId}</name>

   <displayname>${display.name}</displayname>

   <version>${project.version}</version>

   <description>${module.description}</description>

   <vendor>${main.developer}</vendor>

   <components>

   <public>

   <name>XQ_MAILEON_DISPLAY_CHECK</name>

   <description>Panel for showing results of the Maileon DisplayCheck.</description>

   <class>de.espirit.firstspirit.module.GadgetSpecification</class>

   <configuration>

   <gom>de.xqueue.firstspirit.forms.displaycheck.GomDisplayCheck</gom>

   <factory>de.xqueue.firstspirit.forms.displaycheck.DisplayCheckSwingGadgetFactory</factory>

   <value>de.xqueue.firstspirit.forms.displaycheck.DisplayCheckValueEngineerFactory</value>

   <scope unrestricted="yes"/>

   </configuration>

   <resources>

   <!--<resource>lib/xqGeneral-${project.version}.jar</resource>-->
   </resources>

   </public>

   <public>

   <name>CreateMailing Executable</name>

   <displayname>Create mailing</displayname>

   <class>de.xqueue.firstspirit.maileon.mailings.CreateMailingExecutable</class>

   </public>

   <public>

   <name>CopyMailing Executable</name>

   <displayname>Copy mailing</displayname>

   <class>de.xqueue.firstspirit.maileon.mailings.CopyMailingExecutable</class>

   </public>

   <public>

   <name>GetMaileonConfig Executable</name>

   <displayname>Returns the maileon configuration</displayname>

   <class>de.xqueue.firstspirit.contentcreator.GetMaileonConfigExecutable</class>

   </public>

   <public>

   <name>UpdateMailing Executable</name>

   <displayname>Synchronizes a given mailing with Maileon</displayname>

   <class>de.xqueue.firstspirit.maileon.mailings.UpdateMailingExecutable</class>

   </public>

   <public>

   <name>WfUpdateMailingMetadata Executable</name>

   <displayname>Synchronizes the metadata of a given mailing with Maileon</displayname>

   <class>de.xqueue.firstspirit.maileon.mailings.WfUpdateMailingMetadataExecutable</class>

   </public>

   <public>

   <name>ShowMailingInMaileonSA Executable</name>

   <displayname>Show a mailing in SiteArchitect in Maileon</displayname>

   <class>de.xqueue.firstspirit.sitearchitect.mailings.ShowMailingExecutable</class>

   </public>

   <public>

   <name>ShowMailingInMaileonCC Executable</name>

   <displayname>Show a mailing in ContentCreator in Maileon</displayname>

   <class>de.xqueue.firstspirit.contentcreator.mailings.ShowMailingExecutable</class>

   </public>

   <public>

   <name>SendTestmail Executable</name>

   <displayname>Send a testmail to a single emailaddress</displayname>

   <class>de.xqueue.firstspirit.maileon.mailings.SendTestMailExecutable</class>

   </public>

   <public>

   <name>DeleteMail Executable</name>

   <displayname>Delete a mailing</displayname>

   <class>de.xqueue.firstspirit.maileon.mailings.DeleteMailingExecutable</class>

   </public>

   <public>

   <name>Send Mail Executable</name>

   <displayname>Send a mail</displayname>

   <class>de.xqueue.firstspirit.maileon.mailings.SendMailExecutable</class>

   </public>

   <public>

   <name>ShowTargetgroupsInMaileonSA Executable</name>

   <displayname>Show all target groups in SiteArchitect in Maileon</displayname>

   <class>de.xqueue.firstspirit.sitearchitect.targetgroups.ShowTargetgroupsExecutable</class>

   </public>

   <public>

   <name>ShowTargetgroupsInMaileonCC Executable</name>

   <displayname>Show all target groups in ContentCreator in Maileon</displayname>

   <class>de.xqueue.firstspirit.contentcreator.targetgroups.ShowTargetgroupsExecutable</class>

   </public>

   <public>

   <name>UpdateTargetgroups Executable</name>

   <displayname>Update all target groups from Maileon</displayname>

   <class>de.xqueue.firstspirit.maileon.targetgroups.UpdateTargetgroupsExecutable</class>

   </public>

   <public>

   <name>UpdateUsers Executable</name>

   <displayname>Update all users from Maileonn</displayname>

   <class>de.xqueue.firstspirit.maileon.users.UpdateUsersExecutable</class>

   </public>

   <web-app>

   <name>XQ Maileon Preview WebApp</name>

   <displayname>Preview Renderscript Code</displayname>

   <web-xml>web_preview.xml</web-xml>

   <web-resources>

   <resource>lib/xqConfiguration-${project.version}.jar</resource>

   <resource>lib/java-api-client-1.0-SNAPSHOT.jar</resource>

   <resource>lib/java-partner-api-client-1.0-SNAPSHOT.jar</resource>

   </web-resources>

   </web-app>

   <web-app>

   <name>XQ Maileon ContentCreator WebApp</name>

   <displayname>ContentCreator Menu</displayname>

   <web-xml>web.xml</web-xml>

   <web-resources>

   <resource>lib/aopalliance-repackaged-2.5.0-b30.jar</resource>

   <resource>lib/commons-codec-1.10.jar</resource>

   <resource>lib/commons-io-2.5.jar</resource>

   <resource>lib/commons-lang3-3.5.jar</resource>

   <resource>lib/dom4j-1.6.1.jar</resource>

   <resource>lib/gson-2.7.jar</resource>

   <resource>lib/hk2-api-2.5.0-b30.jar</resource>

   <resource>lib/hk2-locator-2.5.0-b30.jar</resource>

   <resource>lib/hk2-utils-2.5.0-b30.jar</resource>

   <resource>lib/java-api-client-1.0-SNAPSHOT.jar</resource>

   <resource>lib/java-partner-api-client-1.0-SNAPSHOT.jar</resource>

   <resource>lib/javassist-3.20.0-GA.jar</resource>

   <resource>lib/javax.annotation-api-1.2.jar</resource>

   <resource>lib/javax.inject-2.5.0-b30.jar</resource>

   <resource>lib/javax.ws.rs-api-2.0.1.jar</resource>

   <resource>lib/jaxen-1.1.6.jar</resource>

   <resource>lib/jersey-client-2.25.jar</resource>

   <resource>lib/jersey-common-2.25.jar</resource>

   <resource>lib/jersey-guava-2.25.jar</resource>

   <resource>lib/json-simple-1.1.1.jar</resource>

   <resource>lib/jsoup-1.9.2.jar</resource>

   <resource>lib/osgi-resource-locator-1.0.1.jar</resource>

   <resource>lib/xml-apis-1.0.b2.jar</resource>

   <resource>lib/xqConnector-${project.version}.jar</resource>

   <resource>lib/xqConfiguration-${project.version}.jar</resource>

   <resource>lib/xqGeneral-${project.version}.jar</resource>

   <resource>lib/xqToolbarCc-${project.version}.jar</resource>

   </web-resources>

   </web-app>

   <!-- Toolbar Menu Item plug-ins -->
   <public>

   <name>Toolbar SiteArchitect</name>

   <displayname>XqSaToolbarItemsPlugin: show items for XQ Maileon newsletters in SiteArchitect</displayname>

   <class>de.xqueue.firstspirit.toolbar.sitearchitect.XqToolbarItemsPlugin</class>

   </public>

   <public>

   <name>Toolbar ContentCreator</name>

   <displayname>XqCcToolbarItemsPlugin: show items for XQ Maileon newsletters in ContentCreator</displayname>

   <class>de.xqueue.firstspirit.toolbar.contentcreator.XqToolbarItemsPlugin</class>

   </public>

   <!-- Services -->

   <service>

   <name>XQueue Configuration Service</name>

   <displayname>Configuration</displayname>

   <description>Provides access to the XQ Maileon configuration.</description>

   <class>de.xqueue.firstspirit.configuration.service.ConfigurationServiceImpl</class>

   <configurable>de.xqueue.firstspirit.configuration.service.ConfigurationServiceConfigPanel</configurable>

   <resources>

   <resource>default-xq_configuration.conf</resource>

   <resource>lib/xqConfiguration-${project.version}.jar</resource>

   <resource>lib/xqGeneral-${project.version}.jar</resource>

   <resource>lib/java-api-client-1.0-SNAPSHOT.jar</resource>

   <resource>lib/java-partner-api-client-1.0-SNAPSHOT.jar</resource>

   </resources>

   </service>

   </components>

   <resources>

   <!-- TODO: make all scope=module again if return value is fixed -->
  <!--<resource scope="module">lib/</resource>-->


   <resource scope="module">lib/aopalliance-repackaged-2.5.0-b30.jar</resource>

   <resource scope="module">lib/commons-codec-1.10.jar</resource>

   <resource scope="module">lib/commons-io-2.5.jar</resource>

   <resource scope="module">lib/commons-lang3-3.5.jar</resource>

   <resource scope="module">lib/dom4j-1.6.1.jar</resource>

   <resource scope="module">lib/gson-2.7.jar</resource>

   <resource scope="module">lib/hk2-api-2.5.0-b30.jar</resource>

   <resource scope="module">lib/hk2-locator-2.5.0-b30.jar</resource>

   <resource scope="module">lib/hk2-utils-2.5.0-b30.jar</resource>

   <resource scope="module">lib/java-api-client-1.0-SNAPSHOT.jar</resource>

   <resource scope="module">lib/java-partner-api-client-1.0-SNAPSHOT.jar</resource>

   <resource scope="module">lib/javassist-3.20.0-GA.jar</resource>

   <resource scope="module">lib/javax.annotation-api-1.2.jar</resource>

   <resource scope="module">lib/javax.inject-2.5.0-b30.jar</resource>

   <resource scope="module">lib/javax.ws.rs-api-2.0.1.jar</resource>

   <resource scope="module">lib/jaxen-1.1.6.jar</resource>

   <resource scope="module">lib/jersey-client-2.25.jar</resource>

   <resource scope="module">lib/jersey-common-2.25.jar</resource>

   <resource scope="module">lib/jersey-guava-2.25.jar</resource>

   <resource scope="module">lib/json-simple-1.1.1.jar</resource>

   <resource scope="module">lib/jsoup-1.9.2.jar</resource>

   <resource scope="module">lib/osgi-resource-locator-1.0.1.jar</resource>

   <resource scope="module">lib/xml-apis-1.0.b2.jar</resource>

   <resource scope="module">lib/xqConnector-${project.version}.jar</resource>

   <resource scope="module">lib/xqConfiguration-${project.version}.jar</resource>

   <resource scope="module">lib/xqGeneral-${project.version}.jar</resource>

   <resource scope="module">lib/xqToolbarSa-${project.version}.jar</resource>

   <resource scope="module">lib/xqToolbarCc-${project.version}.jar</resource>

   </resources>

</module>

Die Aufrufe kommen aus der Toolbar für den SiteArchitect.

Aktuell versuche ich es so:

@Override
public void execute(@NotNull final ContextMenuContext context) {

  Executable executable = new UpdateTargetgroupsExecutable();

  Map<String, Object> param = new HashMap<>();

  param.put("context", context);

  param.put("scope", DualExecutable.SCOPE.SiteArchitect);

  executable.execute(param);

}

Den Teil könnt ihr ignorieren, das ist nur eine interne "Entscheidungsvariable": param.put("scope", DualExecutable.SCOPE.SiteArchitect);

Der Stacktrace sieht dann so aus:

java.lang.NoClassDefFoundError: javax/ws/rs/core/MediaType

    at com.maileon.api.AbstractMaileonService.<clinit>(AbstractMaileonService.java:44)

    at de.xqueue.firstspirit.maileon.targetgroups.TargetgroupsManager.updateTargetgroups(TargetgroupsManager.java:74)

    at de.xqueue.firstspirit.maileon.targetgroups.TargetgroupsManager.updateTargetgroups(TargetgroupsManager.java:59)

    at de.xqueue.firstspirit.maileon.targetgroups.UpdateTargetgroupsExecutable.execute(UpdateTargetgroupsExecutable.java:30)

    at de.xqueue.firstspirit.maileon.targetgroups.UpdateTargetgroupsExecutable.execute(UpdateTargetgroupsExecutable.java:17)

    at de.xqueue.firstspirit.toolbar.sitearchitect.toolbarItems.items.UpdateTargetgroupsToolbarItem.execute(UpdateTargetgroupsToolbarItem.java:28)

    at de.espirit.firstspirit.client.plugin.contextmenu.JavaClientContextMenuItemFactory$1.actionPerformed(JavaClientContextMenuItemFactory.java:48)

    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: java.lang.ClassNotFoundException: javax.ws.rs.core.MediaType

    at java.net.URLClassLoader.findClass(Unknown Source)

    at de.espirit.firstspirit.server.module.ExtendedUrlClassLoader.findClass(ExtendedUrlClassLoader.java:92)

    at de.espirit.firstspirit.server.module.ModuleClassesLoader.findClass(ModuleClassesLoader.java:135)

    at java.lang.ClassLoader.loadClass(Unknown Source)

    at java.lang.ClassLoader.loadClass(Unknown Source)

    ... 48 more

Die Zeile die bemängelt wird erzeugt in der Tat ein neues Objekt von der Klasse MediaType. Die entsprechende Bibliothek finde ich auch in der entsprechenden JAR in der .fsm Datei.

Kann es sich um einen Versionskonflikt handeln? Ich bin mir ziemlich sicher, dass es vor eiiger Zeit ging aber gerade hänge ich seit Stunden an diesem Problem und blicke nicht recht durch was ich falsch mache.

Wenn ich die Executable als Skript ausführe sieht das im Übrigen so aus:

#!executable-class

UpdateTargetgroups Executable

Leider findet auch dies keine der Klassen und ich stehe gerade wirklich auf dem Schlauch...

0 Kudos
1 Solution

Accepted Solutions

Hallo Marcus,

eigentlich hat Jan Dir alles schon erklärt. Wenn etwas in der module.xml als public eingebunden ist (z.B. eine Executable) dann ist diese auf dem Level des FirstSpirit-Servers bzgl. Classloading bekannt. jetzt hängt es stark davon ab, wo die Ressource, z.B. eine Executable, verwendet wird. Im Script, welches im SA aufgerufen wird, wird die Executable client-seitig verarbeitet, hier ist auch der BaseContext oft ein ProjectScriptContext oder sogar ein ClientScriptContext (falls das Script aus dem Context-Menü aufgerufen wurde), der dann spezielle Methoden hat, die einen direkten Zugriff auf das Projekt ohne Umwege wie den ProjectAgent erlaubt bzw. auch Zugriff auf das selektierte Element wie eine PageRef zulässt.

Wird die Executable im Template oder im Script-Task einer Generierung verwendet, so ist der spezielle BaseContext wiederum ein ganz anderer, nämlich ein GenerationContext und wird auf dem Server ausgeführt.

Grundsätzlich würde ich Fremdbibliotheken nie in Executables verwenden, weil es spätestens Probleme mit anderen FirstSpirit-Modulen, wenn nicht mit dem FirstSpirit-Server selbst gibt. Leider testen die wenigsten FSM-Entwickler ihre Module im Zusammenhang mit anderen Modulen, so dass wir immer wieder auf Probleme mit dem Classloading stoßen.

Der Server-Service (es gibt noch Client-Services via Client-Permanent-Plugin, da rauf gehe ich hier nicht ein), wie Jan oben bereits erklärt hatte, ist ein Sonderfall:

- Er wird als public-Komponente zwar angemeldet (class verweist auf die Service-Implementierung), aber er verweist intern auf ein Service(-Java-)-Interface, welches in einem Jar auf Scope Server global im FirstSpirit-Server verfügbar ist. Die Implementierungsklasse, welche dann Fremdbibliotheken verwendet, sollte auf Scope Module sein.

- Alles was im Service-Interface benutzt wird, muss gleiche Sichtbarkeit (also scope server) haben, d.h. alle Klassen in den Methoden des Interfaces

Über Services lassen sich also prima Fremdbibliotheken verbergen, die nicht auf Server-Level sichtbar sein sollen. Dazu gehören auf jeden Fall sämtliche Rest- oder Soap-Bibliotheken etc.... vor allem wenn man nicht weiß, welche Module welche Versionen dieser Bibliotheken verwenden, wie ihr bereits feststellen musstet.

Eigentlich ist es ein Anti-Pattern, zu viel Logik in eine Executable zu packen. Wenn man die Logik nicht in einem Service auslagern kann, dann sollte man mindestens eine normale Java-Klasse benutzen, was auch viel besser testbar ist. Executables oder auch Toolbar-Items dienen dann nur dazu, diese Klassen zu konfigurieren (am besten über den Konstruktor).

Falls ihr Probleme mit dem Erstellen von FSMs habt, dann schaut doch mal bei meinem Maven-FSM-Packagetype vorbei:

https://zaplatynski.github.io/

Ist natürlich etwas opinionated, so FSMs zu bauen, hilft aber, die ganzen Fremdbibliotheken und deren transitiven Abhängigkeiten zu managen. Ich hatte auch mal darüber in meinem Blog berichtet:

[RELEASE] Maven FSM Package Type Version 2.0

Grüße Marian

View solution in original post

0 Kudos
8 Replies
kohlbrecher
Crownpeak employee

Hallo Marcus,

ich denke die Lösung für dein Problem findest du im Kapitel 2.5.1.2 Gültigkeitsbereich im Entwicklerhandbuch für Komponenten.

Aktuell sind die eingebundenen Bibliotheken nur im Modul selber aber nicht auf dem ganzen Server verfügbar. Ich rate dir aber davon ab, die Bibliotheken jetzt einfach auf scope="server" zu setzen, da es so schnell zu Konflikten kommen kann. Der sicheren Weg ist über eine Service-Komponente (eine ServerKomponente, die eine öffentliche Schnittstelle besitzt und somit über Eingabekomponenten oder Scripte angesprochen werden kann; ist immer global, d.h. serverweit.)

Grüße

Jan

0 Kudos

Hi,

das ist etwas merkwürdig weil es ja nun um den SiteArchitect geht und ich sogar die Aufrufe über ein public Interface leite, z.B.:

  1.    <public> 
  2.    <name>UpdateTargetgroups Executable</name> 
  3.    <displayname>Update all target groups from Maileon</displayname> 
  4.    <class>de.xqueue.firstspirit.maileon.targetgroups.UpdateTargetgroupsExecutable</class> 
  5.    </public> 

Ich habe mich eine ganze Weile mit dem Thema Classloading beschäftigt aber ich kann keine Lösung finden. In der Tat würde es vermutlich funktionieren einen serverseitigen Dienst zu entwickeln der einfach "alles" macht aber dann bräuchte gefühlt die ganzen anderen Funktionen und Kapselungen nicht mehr Smiley Happy

Gibt es keine Möglichkeit diese Abhängigkeiten im SiteArchitect verfügbar zu machen? Ich möchte natürlich in Skripten und ähnlichem meine Klassen nutzen die eigentlich immer irgendwelche Abhängigkeiten haben.

Die Klassen sollen im Classloader meines Moduls sichtbar sein (das ich über dieses public Interface aufrufe) aber momentan habe ich nicht das Gefühl, dass das so ist Smiley Sad

MfG Marcus

0 Kudos

Hi Marcus,

<resource scope="module">lib/javax.ws.rs-api-2.0.1.jar</resource>

sorgt dafür, dass MediaType im Modul selber verfügbar ist. Wenn du hier scope="server" setzen würdest, würde es so funktionieren, wie du es gerne hättest. Es ist aber dann nicht garantiert, dass dieses nicht zu Kollisionen mit anderen Versionen der Bibliothek führt.

Der schönste Weg ist daher, den scope auf module zu lassen und einen entsprechenden Service zu implementieren, auch wenn dies mehr Aufwand ist. Dafür ist es im Betrieb deutlich weniger anfällig für Fehler im Zusammenspiel mit anderen Modulen und verschiedenen FS Versionen.

Grüße

Jan

0 Kudos

Hi Jan,

irgendwie habe ich gerade das Gefühl, dass hier mächtig was anders ist als ich es bisher verstanden habe.

Das heißt, wenn ich im SiteArchitect ein Skript habe das z.B. Wetterdaten abholt und dazu einen REST-Service nutzt müsste ich einen Service schreiben der auf dem Server läuft und die Daten abholt um sie in einem SA Plugin anzuzeigen?

Müsste ich dann, sobald ich eine einzige Bibliothek nutze weiterhin public Komponenten definieren auf die ich wie oben geschrieben zugreife und in der Executable dann den Service aufrufen damit dieser die Klassen findet?

Was ich nicht verstehe: wenn ich eine Executable aufrufe wie ich es oben mache, läuft diese dann nicht auch auf dem Server?

MfG Marcus

PS: danke schon einmal

0 Kudos

Hallo Marcus,

nebenbei mal ein anderer Ansatz zu deinem Problem.

Ich hatte ein ähnliches Problem mit der WS-Library und Jersey. Das lag daran,

dass FirstSpirit eine jar enthalten hat, die wiederrum ebenfalls die WS-Library gebundled hat.

Das hat bei mir zu ClassLoader-Fehlern geführt und dann eben auch zu genau dem Problem.

Ist das die glassfish-Variante von Jersey? Auf die musste ich nämlich letztendlich umstellen.

Gruß

Felix

0 Kudos

Hi Felix,

ja... einen Libkonflikt auf dem Applicationserver auf dem der ContentCreator läuft hatte ich leider auch.

Ich nutze in der Tat die Glassfish-Variante:

<dependency>

   <groupId>org.glassfish.jersey.core</groupId>

   <artifactId>jersey-client</artifactId>

   <version>2.25</version>

</dependency>

Ging es bei dir auch um FirstSpirit selbst oder um den Appserver auf dem der CC bzw deine Erweiterung dafür gelaufen ist?

Weswegen mit die Problematik im Übrigen nicht aufgefallen ist bisher: ich habe den SA immer aus meiner IDE gestartet und da findet er dann alle Klassen...

Ich versuche immer noch rauszufinden was mein eigentlicher Fehler ist, wenn ich mir die Doku ansehe müsste auch bei Scope "module" doch der Classloader die Klassen finden, wenn ich diese über die Public Zugangsknoten (Executables) anspreche oder?

wegen der Umstellung auf einen Service zögere ich noch bis ich endgültig verstanden habe was das Problem ist)

MfG Marcus

0 Kudos

Hallo Marcus,

eigentlich hat Jan Dir alles schon erklärt. Wenn etwas in der module.xml als public eingebunden ist (z.B. eine Executable) dann ist diese auf dem Level des FirstSpirit-Servers bzgl. Classloading bekannt. jetzt hängt es stark davon ab, wo die Ressource, z.B. eine Executable, verwendet wird. Im Script, welches im SA aufgerufen wird, wird die Executable client-seitig verarbeitet, hier ist auch der BaseContext oft ein ProjectScriptContext oder sogar ein ClientScriptContext (falls das Script aus dem Context-Menü aufgerufen wurde), der dann spezielle Methoden hat, die einen direkten Zugriff auf das Projekt ohne Umwege wie den ProjectAgent erlaubt bzw. auch Zugriff auf das selektierte Element wie eine PageRef zulässt.

Wird die Executable im Template oder im Script-Task einer Generierung verwendet, so ist der spezielle BaseContext wiederum ein ganz anderer, nämlich ein GenerationContext und wird auf dem Server ausgeführt.

Grundsätzlich würde ich Fremdbibliotheken nie in Executables verwenden, weil es spätestens Probleme mit anderen FirstSpirit-Modulen, wenn nicht mit dem FirstSpirit-Server selbst gibt. Leider testen die wenigsten FSM-Entwickler ihre Module im Zusammenhang mit anderen Modulen, so dass wir immer wieder auf Probleme mit dem Classloading stoßen.

Der Server-Service (es gibt noch Client-Services via Client-Permanent-Plugin, da rauf gehe ich hier nicht ein), wie Jan oben bereits erklärt hatte, ist ein Sonderfall:

- Er wird als public-Komponente zwar angemeldet (class verweist auf die Service-Implementierung), aber er verweist intern auf ein Service(-Java-)-Interface, welches in einem Jar auf Scope Server global im FirstSpirit-Server verfügbar ist. Die Implementierungsklasse, welche dann Fremdbibliotheken verwendet, sollte auf Scope Module sein.

- Alles was im Service-Interface benutzt wird, muss gleiche Sichtbarkeit (also scope server) haben, d.h. alle Klassen in den Methoden des Interfaces

Über Services lassen sich also prima Fremdbibliotheken verbergen, die nicht auf Server-Level sichtbar sein sollen. Dazu gehören auf jeden Fall sämtliche Rest- oder Soap-Bibliotheken etc.... vor allem wenn man nicht weiß, welche Module welche Versionen dieser Bibliotheken verwenden, wie ihr bereits feststellen musstet.

Eigentlich ist es ein Anti-Pattern, zu viel Logik in eine Executable zu packen. Wenn man die Logik nicht in einem Service auslagern kann, dann sollte man mindestens eine normale Java-Klasse benutzen, was auch viel besser testbar ist. Executables oder auch Toolbar-Items dienen dann nur dazu, diese Klassen zu konfigurieren (am besten über den Konstruktor).

Falls ihr Probleme mit dem Erstellen von FSMs habt, dann schaut doch mal bei meinem Maven-FSM-Packagetype vorbei:

https://zaplatynski.github.io/

Ist natürlich etwas opinionated, so FSMs zu bauen, hilft aber, die ganzen Fremdbibliotheken und deren transitiven Abhängigkeiten zu managen. Ich hatte auch mal darüber in meinem Blog berichtet:

[RELEASE] Maven FSM Package Type Version 2.0

Grüße Marian

0 Kudos

Hi Marian,

diese Antwort war sehr ausführlich und super hilfreich fürs Verständnis. Ich werde mir nochmal im Detail ansehen und eventuell mein Maven-Build anpassen aber ich denke das hat meinen Gehirnknoten wieder gerade gerichtet.

Danke! Smiley Happy

0 Kudos