Skip to main content

Modul kann nicht auf eigene Klassen zugreifen (scope=module)

Comments

8 comments

  • Zendesk API User
    Author: Peter_Jodeleit - 5/7/2015 15:28

    Die Hierachie ist anders herum, Scope "modul" kann auf Klassen aus Scope "server" zugreifen, nicht umgekehrt.
    Klassen die in Skripten oder aus anderen Modulen bzw. Scopes benötigt werden, müssen im Scope "server" definiert werden.
    Bei einem Service sollte nur die Schnittstelle im Scope "server" definiert werden, Implementierungsklassen sollten im Scope "modul" liegen.

    0
  • Zendesk API User
    Author: felix_reinhold - 5/7/2015 15:36

    Hallo Peter,

    vermutlich habe ich mich ein wenig umständlich ausgedrückt. Genau so wie du es geschrieben hast mache ich es auch. Die Klassen die ich im Beanshell-Skript nutze liegen im public.jar mit dem scope "server", alle weiteren Klassen die dann diese Klassen nutzen liegen im private.jar. In meinem Beispiel war das:

    Beanshell Skript:

    WsClient client = WsClientFactory.getClient(settings.getSetting("ps_webservice_runtime").getValue());

    WsClient und WsClientFactory liegen im public.jar

    Die WsClient - Klasse könnte bspw. vereinfacht so aussehen:

    package de.hlp.firstspirit.ws;

    import de.hlp.test.HalloWelt;

    public class WsClient  {

      private HalloWelt hw = null;

      public WsClient() {

        hw = new HalloWelt();

      }

    }

    HalloWelt liegt dann im private.jar, dass eine resource mit dem scope "module" ist.


    Da die public.jar und die private.jar beides Ressourcen der gleichen Komponente des gleichen Moduls sind sollte WsClient doch auf HalloWelt zugreifen können (und umgekehrt natürlich nicht), oder?

    0
  • Zendesk API User
    Author: Peter_Jodeleit - 5/7/2015 15:57

    Wie ich schrieb, die Klassen aus einem "global" definiertem Scope können nicht auf Klassen aus dem Scope "modul" zugreifen, auch nicht wenn sie aus dem gleichem Modul kommen.

    0
  • Zendesk API User
    Author: felix_reinhold - 5/8/2015 7:35

    Ah, sorry. Ich sollte die Antworten mal besser lesen. D.h. ich bräuchte entsprechend wieder ein Executable als Einstiegspunkt?

    Dann werde ich nochmal kurz das ursprüngliche Problem formulieren weshalb ich überhaupt auf dieses Thema gekommen bin. Wir verwenden in zwei Modulen die gleiche Library (javax.ws). Bisher hatten wir in Modul 1 nur eine Library mit einer *.jar, die alle Klassen enthält (inkl. javax.ws):

    <library>

         <name>Modul1 Lib</name>

         <resources>

              <!-- enthält eigene Klassen und die dazu benötigten Bibliotheken, wie z.B. javax.ws -->

              <resource>lib/modul1-jar-with-dependencies.jar</resource>

         </resources>

    </library>

    Das Modul 2 besteht aus einer Library und einer Web-App in der zwei jars enthalten:

    <components>

         <web-app scopes="project">

              <name>Modul 2 WebApp</name>

              <version>1.0</version>

              <description>Modul 2 WebApp</description>

              <class>de.hlp.allstar.firstspirit.Modul2App</class>

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

              <web-resources>

                   <resource scope="module">lib/modul2-private.jar</resource> <!-- enthält die benötigten Bibliotheken u.a. javax.ws -->

                   <resource scope="module">lib/modul2-public.jar</resource> <!-- enthält eigene Klassen -->

              </web-resources>

         </web-app>

         <library>

              <name>Modul2 Lib</name>

              <description>Modul 2</description>

              <resources>

                   <resource scope="module">lib/modul2-private.jar</resource> <!-- enthält die benötigten Bibliotheken u.a. javax.ws --> 

                   <resource>lib/modul2-public.jar</resource>  <!-- enthält eigene Klassen -->

              </resources>

         </library>

    </components>

    Nach deiner Erklärung ist mir eigtl. klar, wie das Verhalten dieser Module sein müsste abe rnicht klar, wieso es sich bei uns wie folgt verhält:

    Wir haben ein Skript, dass an 3 Stellen ausgeführt wird und eine Klasse erzeugt die in Modul 1 liegt. Diese Klasse nutzt im Hintergrund Klassen von javax.ws.

    Das Skript wird im JavaClient über einen Button gestartet und funktioniert.

    Das Skript wird im WebClient auf einer Seite per JavaScript über WE_API.Common.execute ausgeführt und funktioniert.

    Das Skript wird im WebClient in einem Formular zur Anlage eines Datensatzes per Button gestartet und schmeißt eine ClassLoader-Exception:

    Target exception: java.lang.LinkageError: ClassCastException: attempting to

    castjar:file:/C:/FirstSpirit5/work/jetty-fs5webedit_269745/webinf/WEB-INF/lib/modul2-private.jar!/javax/ws/rs/ext/RuntimeDelegate.class

    to

    jar:file:/C:/FirstSpirit5/work/ModuleManager/Modul1_79f4545d/lib/modul1-jar-with-dependencies.jar!/javax/ws/rs/ext/RuntimeDelegate.class

    (Habe die Pfade und Namen mal etwas zusammengekürzt).

    Das JavaClient und WebClient sich unterscheiden ist für mich klar, da im WebClient das Modul2 in der WebApp installiert ist.

    Aber wieso gibt es hier ein unterschiedliches Verhalten zwischen WebClient per JS und WebClient per Formular?

    0
  • Zendesk API User
    Author: Peter_Jodeleit - 5/8/2015 13:52

    Hast du die Möglichkeit, das mit einer aktuellen FirstSpirit 5.1 Version zu testen? Oder alternativ in einem Tomcat statt mit dem internem Jetty?

    0
  • Zendesk API User
    Author: felix_reinhold - 5/11/2015 6:34

    Hi Peter,

    habe hier jetzt verschiedene Stände.

    Auf dem 5.1er System ist es ebenfalls, wie oben beschrieben.

    Nun habe ich noch lokal bei mir eine Kopie des Ganzen auf einem 5.0.606er System installiert und hier funktionieren beide WebClient - Variante nicht! Wie wäre denn das richtige Verhalten? Ich kann das dann nochmal probieren mit einem Tomcat nachzuvollziehen. Ich nehme ja mal an, dass Problem kommt daher, dass die Libs der WebApp natürlich unter WEB-INF/libliegen und der WebServer ja nicht "weiß", dass die den scope "module" haben und somit nicht von außen zugreifbar sind, oder?

    Ich teste aber nochmal mit dem Tomcat.


    Gruß

    Felix

    0
  • Zendesk API User
    Author: marza - 6/19/2015 13:52

    Hallo Felix,

    ich habe mir nochmal Gedanken zu dem ClassLoader-Error gemacht. Grundsätzlich sind im Modul-Kontext FAT-Jars eine schlechte Idee, was man auch an dem Error sehen kann (Error != Exception).

    FirstSpirit bzw. Java hat hier per ClassLoader keine Chance zu erkennen, dass sich auf dem Class-Path eine doppelte Definition befindet. Dein Modul 1 ist öffentlich und somit auch im Kontext des Modul 2 lesbar. Je nachdem wie die Klassen auflöst werden bzw. wie im Verlauf des Programmablaufs die Klassen auflöst werden, kommt es zum Konflikt. Dabei "weiß" Java nur, dass der sog. Full-Qualified-Name der Klasse identisch ist. Theoretisch könnten das inhaltlich völlig verschiedene Klassen sein. Aus diesem Grund wird ein Error und keine Exception geworfen.

    Mögliche Lösungen:

    1. Fremdbibliotheken nach Möglichkeit nur Modul-Lokal belassen (Dabei wenn möglich den Originalnamen verwenden, wie dieser z.B. via Maven vergeben wird). Zusätzlich sollte man an den Resource-Tags das Attribut Version setzen (siehe Kaptiel 2.5.1.1 des Modulentwicklerhandbuchs).

    2. Wenn man schon eine Fremdbibliothek als Library-Modul in FirstSpirit verwendet, dann darf man in seinen anderen Modulen die gleichen Packages und Java-Klassen nicht mehr mitliefern, vor allem nicht in FAT-Jars. Man sollte dann auch eine Modul-Abhängigkeit eintragen (siehe Kapitel 3.8 des Modulentwicklerhandbuchs), damit der Fall abgefangen wird, dass das Libraray-Modul vor den anderen Modulen deinstalliert wird.

    Ich hoffe ich konnte Dir weiterhelfen.

    Grüße

    Marian Zaplatynski

    0
  • Zendesk API User
    Author: felix_reinhold - 6/23/2015 6:37

    Hi Marian,

    danke für die Antwort und die Tipps.

    Dann werden wir wohl bei uns im Produkt jetzt einiges umstellen müssen ;-)

    Gruß

    Felix

    0

Please sign in to leave a comment.