Search the FirstSpirit Knowledge Base
Hi,
ich bin nun dabei mich wieder in FirstSpirit einzuarbeiten und lagere Funktionen aus Executables in Dienste aus. Grund hierfür war eine Empfehlung damals, dass Funktionen die aus dem ContentCreator, dem SiteArchitect und dem Server (regelmäßige Jobs) aufgerufen werden können und relativ lange laufen können (Synchronisierung von Daten), in Dienste auslagern soll. Dabei habe ich jedoch Umgehend wieder die Bekanntschaft mit der JAR-Hölle machen dürfen und hoffe Ihr könnt mir etwas Klarheit verschaffen.
Szenario: ich habe 2 Dienste, welche angeboten werden und eine Bibliothek X, hier zu Demonstrationszwecken eine WS API, nutzen. Im Groben dachte ich, dass ich das Modul wie folgt beschreibe:
<?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>
... einige Executables ...
<service>
<name>XQueue Configuration Service</name>
<displayname>Configuration Service</displayname>
<description>Provides access to the XQ Maileon configuration.</description>
<class>de.xqueue.firstspirit.services.configuration.ConfigurationServiceImpl</class>
<configurable>de.xqueue.firstspirit.services.configuration.ConfigurationServiceConfigPanel</configurable>
</service>
<service>
<name>XQueue Targetgroup Service</name>
<displayname>Targetgroups Service</displayname>
<description>Provides access to the XQ Maileon targetgroups.</description>
<class>de.xqueue.firstspirit.services.targetgroups.TargetgroupsServiceImpl</class>
</service>
</components>
<resources>
<resource scope="module">lib/javax.ws.rs-api-2.0.1.jar</resource>
</resources>
</module>
Das führte natürlich zu einer ClassNotFoundException, da die Dienste serverweit sichtbar sind und somit der Scope der Bibliothek nicht greift. In der Doku konnte ich dies auch nachlesen, ok, mein Fehler. Also definierte ich die Datei wie folgt um:
<?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>
... einige Executables ...
<service>
<name>XQueue Configuration Service</name>
<displayname>Configuration Service</displayname>
<description>Provides access to the XQ Maileon configuration.</description>
<class>de.xqueue.firstspirit.services.configuration.ConfigurationServiceImpl</class>
<configurable>de.xqueue.firstspirit.services.configuration.ConfigurationServiceConfigPanel</configurable>
<resources>
<resource>lib/javax.ws.rs-api-2.0.1.jar</resource>
</resources>
</service>
<service>
<name>XQueue Targetgroup Service</name>
<displayname>Targetgroups Service</displayname>
<description>Provides access to the XQ Maileon targetgroups.</description>
<class>de.xqueue.firstspirit.services.targetgroups.TargetgroupsServiceImpl</class>
<resources>
<resource>lib/javax.ws.rs-api-2.0.1.jar</resource>
</resources>
</service>
</components>
<resources>
<resource scope="module">lib/javax.ws.rs-api-2.0.1.jar</resource>
</resources>
</module>
Das führt beim Deployment dazu, dass ich einen Fehler bekomme:
ERROR 26.04.2018 09:15:47.422 (de.espirit.firstspirit.server.module.ModuleManagerImpl): module xqFsm: conflict detected, resource will be ignored (lib/javax.ws.rs-api-2.0.1.jar): de.espirit.firstspirit.server.module.ResourceConflictException: duplicate resource: lib/javax.ws.rs-api-2.0.1.jar
Wird die Resource nun mit Scope "server" deployed und deshalb abgelehnt?
In ResourceConflictException bei der Modulinstallation hatte ich gelesen, dass man im Dienst auch einen Scope nutzen kann aber ich glaube das habe ich falsch verstanden, das ergibt nicht viel Sinn.
Wie kann ich dem Dienst denn eine Bibliothek mitgeben die nur für den Dienst zuständig ist ohne gleich im ganzen Server herumzupfuschen? Oder "ist das dann halt so"?
Hallo Marcus,
als "best-practice" hat sich in unseren Modulen folgender Weg etabliert:
Wir haben ein jar, welches die Interfaces unserer Services enthält und binden dieses als Modulresource mit scope="server" ein. Daneben haben wir ein jar, welches die Implementierungen unserer Services enthält und binden dieses als Modulresource mit scope="module" ein. Weitere Libraries, die von unseren Implementierungsklassen benötigt werden, können dann ebenfalls als Modulresource mit scope="module" eingebunden werden. Dadurch, dass unsere Implementierungsklassen und die Drittlibraries alle im Modulscope liegen, finden sie sich gegenseitig. Im Serverscope haben wir somit nur die Interfaces der Services liegen.
Viele Grüße
Donato
Hallo Marcus,
als "best-practice" hat sich in unseren Modulen folgender Weg etabliert:
Wir haben ein jar, welches die Interfaces unserer Services enthält und binden dieses als Modulresource mit scope="server" ein. Daneben haben wir ein jar, welches die Implementierungen unserer Services enthält und binden dieses als Modulresource mit scope="module" ein. Weitere Libraries, die von unseren Implementierungsklassen benötigt werden, können dann ebenfalls als Modulresource mit scope="module" eingebunden werden. Dadurch, dass unsere Implementierungsklassen und die Drittlibraries alle im Modulscope liegen, finden sie sich gegenseitig. Im Serverscope haben wir somit nur die Interfaces der Services liegen.
Viele Grüße
Donato
Hier findet man noch ein paar Hinweise: https://community.e-spirit.com/message/12765
Wie Donato schreibt: Modulresource ist der Schlüssel, also nicht in einer "library" oder einem "service".
... wobei ich das Classloading in FS zugegeben so überhaupt nicht verstanden habe.
Hi,
danke zunächst für die Antworten. Ich habe es nun einmal testweise mit 3 Services umgesetzt und in der Tat, aus irgend einem Grund funktioniert das nun. Mir ist nun aber auch nicht ganz klar, wieso der Service nun auf die modulinternen Resourcen zugreifen kann, mit dem extra Serviceinterface-Package das serverweit bekannt ist funktionieren die Aufrufe allerdings nun. Man muss natürlich peinlichst darauf achten, dass man nur serialisierbare Elemente übergibt und dazu sind einige Änderungen notwendig, insgesammt scheint es aber nun zu passen.
MfG Marcus