a_reg
I'm new here

Workflow mit Service im ContentCreator nutzen

Jump to solution

Hallo,

 

ich habe eine Frage bezüglich der Notwendigkeit einer <web-app> in Verbindung mit <service> Komponenten, die auch im ContentCreator zugänglich sein sollen.

In unserern Workflows werden bestimmte Drittsysteme angesprochen. Die Anbindung ist über die Implementierung von <service> Komponenten gelöst  (.getService(..)). Unter der bisherigen FS 4.2 Installation sind die Services auch bei Ausführung der Workflows im Web-Edit out-of-the-box verfügbar, obwohl WebEdit auf einem externen Tomcat läuft. Unter FS 5.1 (R2) erhalten wir nun beim Ausführen der Workflows im ContentCreator eine ServiceNotFoundException.

Ein Anlegen und deployen einer <web-app> mit enprechenden Klassen auf dem ContentCreator-Server löst zwar das Problem (der Service kann gefunden und gecastet werden), jedoch wollte ich an dieser Stelle doch noch mal einmal nachfragen ob dies wirklich notwendig ist (da es ja unter 4 auch ohne klappte).

Bezüglich Editor-Komponenten, Workflow  Group  Provider-,  Store Mapping-  oder  Report-Plugins gibt es dazu ja bereits entsprechende Hinweise in der Admit/Developer Doku und diversen Community Beiträgen (How to fix failing service calls in a web environment).

Grund der Frage ist, dass bei uns der ContentCreator auf dem Tomcat NICHT über die FS Admin-Einstellungen konfiguriert wird (und somit darüber auch keine we-apps deployed werden können) und wir gerne den Aufwand sparen möchten, auf allen Projekten (3 Stages, teilweise >20 Projekte pro Stage) jeweils auch noch die web-apps zu installieren. Meines Wissens gibt es keine "globalen" (projekt-übergreifenden) ContentCreator Web-apps. Oder gibt es eine einfache Alternative, die ich übersehe?

Als Quick-fix haben wir zZ. die service-jar dem Tomcat-Klassenpfad hinzugefügt, sodass der service nun in allen Projeckten global auch im ContentCreator zur Verfügung steht. Das ist natürlich keine Dauerhafte Lösung da Implementierungsänderung manuell auf den Tomcat kopiert werden müssen.

Grüße,

Andreas

1 Solution

Accepted Solutions
AuM
I'm new here

So, nun ist das Rätsel gelöst!

Der Grund warum sich in Post https://community.e-spirit.com/message/22690#22690 der Fall 2 und 3 nicht unterschieden haben lag in unserem JAR-File begründet. Über eine transitive Abhängigkeit hat sich die Servlet API in unser JAR-File geschlichen, so dass der Tomcat es für das Classloading ignoriert hat (http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html: "...any JAR file that contains Servlet API classes will be explicitly ignored by the classloader — Do not include such JARs in your web application...").

Da die Klassen dann gemäß der Classloading Hierarchie vom FS-Modul Classloader gezogen wurden kam es zum beschriebenen Fehlerbild.

Die Korrekte Lösung (ohne Nutzung von custom Web-Applikationen) ist also das Verschieben der fs-webrt.jar sowie der custom JARs in das WEB-INF/lib Verzeichnis der entsprechenden ContentCreator / Preview Applikationen.

Vielen Dank für die Unterstützung bei der Fehlersuche!

Martin

View solution in original post

0 Kudos
14 Replies
king
I'm new here

Hallo Andreas,

wir haben eine Passage in der FirstSpirit Module-Developer Dokumentation in Kapitel 2.10.2 gefunden, die das Problem beseitigen helfen können sollte. Allerdings ist hier explizit die Rede von IBM WebSphere. Wir verwenden jedoch Apache Tomcat, hier in Version 7.0.54.

Dabei wird vorgeschlagen, die "fs-webrt.jar" nicht zentral über den Tomcat Standard-Classloader  sondern je FirstSpirit Web-Applikation vorzuhalten und dabei über den sog. WebApp-Classloader laden zu lassen. Ziel ist: Klassen nicht über unterschiedliche Classloader zu verwenden und dadurch deren Verwaltung zu trennen. Diesen Schritt haben wir manuell versucht, in dem wir sowohl die gesamte JAR aus dem Modul mit den Services als auch die JAR "fs-webrt.jar" in sämtlichen FirstSpirit-spezifischen Web-Applikationen "/fs5webedit", "/fs5preview", "/fs5staging", "/fs5root" bereitgestellt haben. Das Ergebnis überraschte: der Aufruf der "getService()"-Methode war weiterhin NICHT möglich.

Die Variante eine dedizierte WebApp über ein Modul bereitzustellen und dann auf dem Applikationsserver zu deployen macht jedoch genau das auch: beim Download der "WAR"-Datei aus FirstSpirit heraus wird die "fs-webrt.jar" implizit in das WAR-Archiv zu den dort bestehenden Bibliotheken gelegt, die Teil der Web-Komponente sind. Zusammen werden sie dann über für den Classloader verfügbar gemacht. Wir haben diesen Schritt auch deshalb nicht explizit hier versucht, weil schon dere obere fehlschlug.

Allerdings - und das interssant - klappt dann der Aufruf der "getService()"-Methode wenn die Service-Klassen explizit im Standard-Classloader neben der "fs-webrt.jar" liegen, also unter ~tomcat/lib. Jedoch mussten wir die JAR mit den FirstSpirit Service-Methoden um gewisse Pakete reduzieren, etwas solche, deren Klassen in FirstSpirit-Templates statisch aufgerufen werden. Als Beispiel sei die "PermaLink"-Klasse genannt:

permaLink = PermaLink.getPermaLink(gc, e, languageId, contentId, e.getProject().getName() + "_", "html");

Bei beiden eingangs beschriebenen Wegen:

  1. manuelle Kopie,
  2. WebApp-Anwendung

würde allerdings dann die Empfehlung aus Kapitel 4.5.3 der "FirstSpirit Dokumentation für Administratoren" beim Setup über einen externen Applikationscontainer nicht befolgt werden können. Hier wird vorgeschlagen, die "fs-webrt.jar" zentral abzulegen und über die zentrale Tomcat Konfigurationsdatei "catalina.properties" zu integrieren.

Deshalb folgende Fragen:

- warum klappt der Aufruf von Services über "getService()" dann nicht wenn deren Klassen neben der "fs-webrt.jar" in den FirstSpirit Web-Applikationen liegen?

- warum ist der Aufruf Möglich wenn beide Teile über den Standard-VM-Klassenlader von Tomcat geladen werden, sie also etwa in ~tomcat/lib liegen?

- warum braucht es eine Reduzierung diverser Klassen, weil bei der sonst für eine fehlerfreie Nutzung im ContentCreator schädlich sind?

- wie können diese Klassen identiziert werden?

- warum gibt es keine Möglichkeit eine zentrale FirstSpirit ContentCreator Web-Anwendung über FirstSpirit zu bauen, die NICHT project-spezifisch ist?

0 Kudos

Ich habe drei Fälle ausprobiert und die Resultate (Classloader und Möglichkeit der Service-Aufrufe) beschrieben. Für jeden Fall habe ich erwähnt wo die fs-webrt.jar, sowie unsere service.jar deployed sind und über welche Classloader der Service sowie die FirstSpirit Connection (context.getConnection()) geladen wurden.

Der u.g. statische Methodenaufruf bezieht sich auf ein Beanshell-Script, welches in der Seitengenerierung verwendet wird und eine statische Methode aus einer Klasse des Service-JARs aufruft. Diese statische Methode hat folgende Signatur:

public static String getPermaLink(final GenerationScriptContext context, final IDProvider element,final String languageId, final String contentId, final String uidPrefix, final String templateSet) {

In den Fällen in denen die Methode in der Seiten-Preview nicht aufrufbar war vermuten wir stark, dass die Signatur nicht gematched hat, da das Objekt vom Typ GenerationScriptContext aus einem anderen Classloader stammt, als die Klasse der o.g. statischen Methode.

Fs-WebRT in tomcat/lib

Service-JAR in tomcat/lib:

Service: org.apache.catalina.loader.StandardClassLoader@5b8b3f9a,

Connection: WebappClassLoader context: /fs5webedit delegate: false repositories: ----------> Parent Classloader: org.apache.catalina.loader.StandardClassLoader@5b8b3f9a

Service Aufruf OK, Statischer Methoden Aufruf nicht OK

Fs-WebRT in tomcat/lib

Service-JAR in fs5webedit/lib:

Service: de.espirit.firstspirit.server.module.ModuleClassesLoader@13b56e1d-81,

Connection: WebappClassLoader context: /fs5webedit delegate: false repositories: ----------> Parent Classloader: org.apache.catalina.loader.StandardClassLoader@114662e3

Service Aufruf nicht OK, Statischer Methoden Aufruf OK

Fs-WebRT in tomcat/lib

Service-JAR not deployed:

Service: de.espirit.firstspirit.server.module.ModuleClassesLoader@49a2e909-101,

Connection: WebappClassLoader context: /fs5webedit delegate: false repositories: ----------> Parent Classloader: org.apache.catalina.loader.StandardClassLoader@12fcc66a

Service Aufruf nicht OK, Statischer Methoden Aufruf OK

Wir haben, erfolglos, ebenfalls versucht die fs-webrt.jar mit in die WEB-INF/lib zu deployen, konnten jedoch keine Verbesserung feststellen.

Warum unterscheiden sich Fall 2 und Fall 3 nicht? Ich hätte für Fall 2 erwartet, dass der Service über den WebAppClassLoader geladen wird, da die JAR in der WEB-IN/lib deployed ist.

Der Vollständigkeit halber anbei noch das Script zum Testen der Service-Aufrufe:

//!Beanshell

import com.bosch.fsm.dialogue.DialogueHelper;

import de.espirit.firstspirit.store.access.pagestore.PageImpl;

import de.espirit.firstspirit.store.access.pagestore.SectionImpl;

import de.espirit.firstspirit.store.access.contentstore.Content2Impl;

import de.espirit.or.schema.Entity;

import com.bosch.fsm.ams.ActivityManagerServiceImpl;

service = new ActivityManagerServiceImpl();

DialogueHelper.showInfoDialogue(context, "Classloaders",  "Service: " + service.getClass().getClassLoader().toString() + ", Connection: " + context.getConnection().getClass().getClassLoader().toString());

try {

    someService = context.getConnection().getService("ActivityManagerService");

    DialogueHelper.showInfoDialogue(context, "Service found",  "Everything fine.");

} catch(Exception e) {

    DialogueHelper.showErrorDialogue(context, "Service not found",  "Nothing fine.", e);

}

0 Kudos

Fs-WebRT in tomcat/lib

Service-JAR in tomcat/lib:

Service: org.apache.catalina.loader.StandardClassLoader@5b8b3f9a,

Connection: WebappClassLoader context: /fs5webedit delegate: false repositories: ----------> Parent Classloader: org.apache.catalina.loader.StandardClassLoader@5b8b3f9a

Service Aufruf OK, Statischer Methoden Aufruf nicht OK

Das "Connection: WebappClassLoader context: /fs5webedit" deutet darauf hin, das in "fs5webedit/lib" noch FirstSpirit-Klassen liegen. Dies führt dazu, das der Tomcat diese "bevorzugt". Damit kommt es dann zu der von dir auch schon vermuteten Inkompatibilität.

Wichtig ist, dass die Klassen, die interagieren müssen, über den gleichen ClassLoader kommen.

Entfernt ihr also aus dem "fs5webedit/lib" Verzeichnis die Libs, die Klassen enthalten, die auch unter "tomcat/lib" liegen, sollten beide Fälle funktionieren.

Peter
0 Kudos

Hallo Hr. Jodeleit,

vielen Dank erstmal für die Antwort.

Die Vermutung, dass FirstSpirit Klassen in der WebApp liegen ist insofern richtig, dass es die Standard-FS-Webedit WebApp ist und diese natürlich FirstSpirit Jars mitbringt (fs-webedit.jar, etc.). Daran möchten wir jedoch auch nichts ändern und diese nicht in das tomcat/lib Verzeichnis verschieben.

Viel wichtiger für mich ist der zweite genannte Fall (custom-services.jar + fs-webrt.jar in WEB-INF/lib). Hierbei verstehe ich nicht, wieso die Services dort von ModulesClassloader gezogen werden und nicht aus der WebApp. M. M. n. erzeugt dieser Fall eine äquivalente Web-Applikation wie ein Inkludieren einer FS-Modul WebApp Komponente in die ContentCreator Applikation und sollte daher ohne Abstriche sowohl für Service-Aufrufe, als auch statische Methodenaufrufe aus der Preview funktionieren, oder?

In diesem Fall wären dann sowohl Services, FS-Jars und statische Klassen in dem gleichen Classloader (WebappClassloader) und die Probleme sollten vermutlich verschwunden sein.

Habe ich hier einen Gedankenfehler oder gibt es einen besseren Weg?

Vielen Dank und Gruß

Martin

P. S.

Der Grund warum wir keine WebApp-Komponente im FirstSpirit Modul nutzen liegt darin begründet, dass wir pro Stage rd. 20 Projekte haben und in diesem Fall ca. 60 Custom ContentCreator + Preview WebApps deployen und betreiben müssten. Die Möglichkeit eigene Web-Komponenten zentral, also ein mal pro Stage in die ContentCreator / Preview WebApps hinzuzufügen gibt es ja (noch) nicht für eigene Erweiterungen (https://community.e-spirit.com/message/21592#21592).

Wir wollen den betrieblichen Overhead / zusätzlichen Ressourcenverbrauch der vielen WebApps vermeiden und versuchen daher die relevanten Jar-Files per Dateisystem in die FirstSpirit WebApps zu integrieren.

0 Kudos

Viel wichtiger für mich ist der zweite genannte Fall (custom-services.jar + fs-webrt.jar in WEB-INF/lib). Hierbei verstehe ich nicht, wieso die Services dort von ModulesClassloader gezogen werden und nicht aus der WebApp.

Das ist (in eurem Fall "leider") ein Implementierungs-Detail. Solange man nach der Empfehlung vorgeht, stört dieses Detail auch nicht.

Ich verstehe das Problem und den Anwendungsfall aber durchaus. Eine Änderung der Verfahren in dem Umfeld birgt allerdings ein hohes Risiko und muss bezüglich Kompatibilität genau evaluiert werden.

Peter
0 Kudos

Hallo Herr Jodeleit,

könnten Sie bezüglich der Empfehlungen (P. Jodeleit, H. Isenberg) von e-Spirit konkret werden?  Wie verhält es sich mit dem "Entwicklerhandbuch für Komponenten" in Kapitel 2.10.2 und der Aussage in Kapitel 4.5.3 der "Dokumentation für Administratoren".

Nach unserem Verständnis sind wir mit Ansatz (2) durch Ablage der beiden Bibliotheken "fs-webrt.jar" und der individuellen "services.jar" innerhalb von "/fs5webedit" Ihren Wünschen gefolgt. Jedoch zeigte sich hier, wie im Fall (2) von Martin Aulich beschrieben, dass dieser nicht trägt. Da selbst der Service nicht gerufen werden konnte.

Da sich in der Dokumentation unterschiedliche Aussagen und Empfehlungen finden würden wir gerne verstehen:

  • welche Teile in welche JARs gepackt werden müssen
  • wo diese liegen sollen

Augenscheinlich werden identische Klassen über unterschiedliche Classloader angezogen. Dies führt zu den hier beschriebenen Problemen.

0 Kudos

Eine kleine Ergänzung von mir:

Wenn ich mich nicht irre ist die Empfehlung (siehe: https://community.e-spirit.com/community/developer/blog/2014/03/27/how-to-fix-failing-service-calls-...) die eigene Jar mit den Services sowie deren Abhängigkeiten als Web-Komponente dem ContentCreator hinzuzufügen, korrekt?

Wie unterscheidet sich unser Szenario Nr. 2 (manuelles Kopieren der Jars in die Standard FS-WebApps) von der Empfehlung? Wenn ich exemplarisch eine WebApp Komponente mit einer eigenen Jar an den ContentCreator hänge und mir das WAR File downloade wirken beide WebApps äquivalent. Ich verstehe aktuell nicht, warum der Weg über FirstSpirit WebApp Komponenten funktionieren soll und der Weg über manuelles Integrieren der Jars nicht. Vergessen wir da etwas?

0 Kudos

Mit Fall 2) ist "Fs-WebRT in tomcat/lib und Service-JAR in fs5webedit/lib" gemeint?

Peter
0 Kudos

Ja, mit Fall 2) meinte ich folgendes Szenario:

Fs-WebRT in tomcat/lib

Service-JAR in fs5webedit/lib:

Wobei wir als Abwandlung (siehe mein erster Post) ebenfalls die fs-webrt.jar von tomcat/lib in fs5webedit/lib verschoben haben - leider ohne positiven Effekt.

0 Kudos