Skip to main content

Wie baue ich eine Library (Bibliothek) Komponente

Comments

7 comments

  • Zendesk API User
    Author: NMc - 1/25/2019 16:13

    Moin Olli,

    Ich bin wirklich kein Profi was die module.xmls angeht, aber die Doku sagt mir, dass du prinzipiell den richtigen Weg gehst.

    Siehe hier https://docs.e-spirit.com/odfs/vorlagenentwick/vorlagensyntax/funktionen/anweisungen/class/index.html

    <library>

    <name>MeinModul-library</name>

    <resources>

    <resource>lib/mymodule-1.0.0-SNAPSHOT.jar</resource>

    <resource name="com.example.package" scope="server" version="1.0.0-SNAPSHOT">lib/myclasscontainer-1.0.0-SNAPSHOT.jar</resource>

    </resources>

    </library>

    Wenn du das in deiner module.xml stehen hast, sollte es eigentlich möglich sein mit folgendem Befehl statische Funktionalitäten deiner Klasse MyClass aufzurufen:

    $CMS_VALUE(class("com.example.package.MyClass").methode())$

    (Willst du auf nicht statische Inhalte zugreifen, musst du die Klasse natürlich zuvor instanziieren.)

    Dabei sollte sich in deinem Lib-Ordner natürlich eine

    mymodule-1.0.0-SNAPSHOT.jar (= Das eigentliche Modul) und eine

    myclasscontainer-1.0.0-SNAPSHOT.jar (= Dort liegt die Logik, die du aus dem Template aufrufen möchtest)

    befinden.

    Ich hoffe ich konnte dir weiterhelfen,

    Gruß

    Nico

    0
  • Zendesk API User
    Author: oboeck - 1/25/2019 16:29

    Hmm... für mich ist die Unterscheidung zwischen:

    • <resource>lib/mymodule-1.0.0-SNAPSHOT.jar</resource> 

    und

    • <resource name="com.example.package" scope="server" version="1.0.0-SNAPSHOT">lib/myclasscontainer-1.0.0-SNAPSHOT.jar</resource>

    irgendwie nicht verständlich... wenn ich das fsm baue landet einfach nur eine einzige tika-document-parser-1.0.0-SNAPSHOT.jar innerhalb der tika-document-parser-1.0.0-SNAPSHOT.fsm unterhalb des LIB Folders (und natürlich alle möglichen dependencies die da so über die pom.xml rumliegen)... was aber meines wissens glaube ich durch folgende Zeite passiert

    1. <module>  
    2.     <resources> 
    3.         ${module.resources.global.legacy} 
    4.     </resources>
    5. <module>  

    Inhalt der tika-document-parser-1.0.0-SNAPSHOT.fsm im lib-Folder:

    Und innerhalb der tika-document-parser-1.0.0-SNAPSHOT.jar dann halt meine eigentlichen Java Klassen.

    Was ist der unterschied zwischen mymodule-1.0.0-SNAPSHOT.jar und myclasscontainer-1.0.0-SNAPSHOT.jar

    0
  • Zendesk API User
    Author: mbergmann - 1/25/2019 20:10

    Hallo Olli,

    die FileNotFoundException sieht erstmal stark danach aus, als ob die jar mit einem anderen Namen/Pfad im FSM liegt als in der erzeugten module.xml angegeben. Schau bitte mal in das erzeugte FSM rein, ob der Pfad aus in der darin enthaltenen module.xml mit dem tatsächlichen Ablageort im FSM übereinstimmt. Das heißt, da stimmt schonmal was nicht. Bevor diese Fehlermeldung nicht weg ist, brauchst du andere Dinge gar nicht erst versuchen ;-)

    Richtig, <public> bringt nur etwas wenn es sich um die Implementierung eines dafür vorgesehenen Interfaces aus der FS-API handelt, z.B. ein Plugin oder Executable.

    Eine Library-Komponente funktioniert da grundsätzlich schon - zumindest wenn man diesen Weg gehen will (s.u. für eine vielleicht bessere Alternative(n)). Ein jar reicht hier - Nicos Beispiel passt eher zu einem anderen Fall bzw. es wird glaube ich nicht ganz klar dass mit der "anderen" jar eine Fremd-Lib gemeint war. Die brauchst du natürlich.

    Außerdem nutzt Du aktuell beim Aufruf die Syntax zum Aufruf einer ​statischen ​Methode. Willst Du ein Objekt, brauchst Du tatsächlich ein class(...).new(), siehe hier (aber hattes Du ja auch schon probiert - was aber eben wegen dem Problem bei der Installation nichts gebracht hat).

    Letztlich kommen hier mehrere Dinge zusammen. Erster Schritt wäre, die FileNotFoundException bei der Modulinstallation loszuwerden. Dann erstmal testen ob die Klasse wirklich da ist z.B. mit $CMS_VALUE(class("...").getName())$ im Template. Dann erst das echte Parsen.

    Ein weiteres grundsätzliches Problem an der Sache ist aber, dass - wenn Du die Klasse "direkt" nutzen willst, die entsprechende JAR im "server scope" zur Verfügung gestellt werden muss. Solange das nur eine eigene Klasse ist, ist das nicht so problematisch - das eigentliche Problem sind dann eher die Abhängigkeiten (=Fremd-Libs) die Du mitbringst. Damit die in FS dann aus Deiner Klasse heraus nutzbar sind, müssen deren jars dann auch in den Server scope. Und das kann irgendwann zu Konflikten führen, wenn die (später vielleicht...) auch von anderen Modulen genutzt / mitgebracht werden - aber in einer anderen Version. Da bringt die Nutzung von Executables den Vorteil, dass man die (und damit auch deren Abhängigkeiten) in den module scope legen kann und dann die Modul-Ressourcen voneinander abgeschottet sind.

    Wenn die Executable dann als <public> Komponente implementiert wird, ist sie über ihren Namen zugreifbar (über den Umweg über ein kleines Skript). Wichtig: <public> ist was anderes als scope="public", bei Executables greift da ein "Spezialmechanismus". Wie man sowas grundsätzlich bauen kann, habe ich hier mal beschrieben. Damit passiert die Ausgabe nicht "direkt" über das Executable (ginge zwar auch, ist für meinen Geschmack aber zuviel "Magie" und unflexibel), sondern es wird eher als eine Art "Factory" genutzt um sich Instanzen eigener Klassen geben zu lassen. Auf denen kann man dann Methoden aufrufen.

    Letztlich hat die direkte Nutzung des Klassennamens bzw. des FQCN auch noch den Nachteil, dass es nicht refactoring-sicher ist, Executables führen über ihren <name> quasi eine zusätzliche „Abstraktionsschicht“ ein.

    Alternative

    Ich könnte mir vorstellen, dass das Parsen des PDF - vor allem bei jedem Aufruf / jeder Generierung - nicht ganz effizient ist. Vielleicht wäre es hier besser, einen UploadHook zu implementieren, der beim Hochladen bzw. Aktualisieren des PDF dieses EINMAL parst und den Text dann in den Metadaten des Medienobjektes ablegt. Oder ggf. auch in einer detaillierteren Struktur (=mehrere Eingabekomponenten) dort.

    Viele Grüße

    Michael

    0
  • Zendesk API User
    Author: mbergmann - 1/26/2019 11:56

    Hallo Olli,

    ich hatte bei meiner ursprünglichen Antwort zwei Dinge durcheinander geworfen - habe sie mal entsprechend geändert.

    Viele Grüße

    Michael

    0
  • Zendesk API User
    Author: oboeck - 1/31/2019 7:59

    Hallo Michael,

    erst einmal vielen lieben Dank für die ausführliche Beschreibung, das hat schon einiges geholfen!

    Den Grund warum die FileNotFoundException geworfen wurde habe ich finden können. Ich hatte einen Fehler in der pom.xml dort hatte ich als artifactID = tika-document-parser eingetragen.

    Die von e-Spirit bereitgestellte fsm-parent-pom + module-resource-plugin haben dann eine .jar Datei erzeugt die tika-document-parser-1.0.0.jar hieß.

    Aber im Modul Deskriptor für die Ressource stand als Name hinter dem Doppelpunkt der Package Name aus dem eigentlichen Projekt. Deswegen konnte er die jar nicht finden, weil er eigentlich eine  documentparser-1.0.0-SNAPSHOT.jar erwartet hat.

    <resource name="de.xxx.firstspirit.module:documentparser">lib/tika-document-parser-1.0.0-SNAPSHOT.jar</resource>

    Nichts desto trotz habe ich mich auf Grund deines Hinweises bzgl. der module und server Scope Thematik gegen eine LIBRARY Komponente entschieden und stattdessen eine PUBLIC Komponente mit einem Executable verwendet.

    Erstes Hindernis war allerdings das die Executable im "server"-Scope vorhanden sein muss, sonst konnte ich Sie im Script-Template nicht aufrufen. Dort kam dann auch immer ClassNotFound so lange sich die documentparser-1.0.0-SNAPSHOT.jar nicht im scope="server" befand.

    Danach funktioniert das auch soweit die Klasse per Skript aufzurufen. Allerdings haben alle anderen Module die ich bisher gebaut habe nie so viele Dependencies benötigt.

    Ich habe jetzt das Problem, das ich zwar die Executable aufrufen kann, aber diese nutzt ja unter der Haube diese ganzen anderen libs und jetzt sag er mir das er zu diesen die Klassen nicht finden kann. Ich vermute weil diese im scope="module" sitzen?

    Ich habe schon angefangen diese nach und nach in der plugin configuration des module-resource-plugins innerhalb der pom.xml auf scope="server" zu setzten, aber ich denke nicht dass das der richtige Weg ist, oder?

    <build>

        <pluginManagement>

            <plugins>

                <plugin>

                    <groupId>com.espirit.ps.psci</groupId>

                    <artifactId>module-resource-plugin</artifactId>

                    <version>0.1</version>

                    <executions>

                        <execution>

                            <id>generate-module-resources</id>

                            <phase>generate-resources</phase>

                            <goals>

                                <goal>generate</goal>

                            </goals>

                            <configuration>

                                <resources>

                                    <resource>

                                        <scope>server</scope>

                                        <identifier>${project.groupId}:${project.artifactId}</identifier>

                                        <path>lib/${project.artifactId}-${project.version}.jar</path>

                                    </resource>

    <!--

                                    <resource>

                                        <scope>server</scope>

                                        <identifier>org.apache.tika:tika-core</identifier>

                                        <path>lib/</path>

                                    </resource>

    -->

                                </resources>

                            </configuration>

                        </execution>

                    </executions>

                </plugin>

            </plugins>

        </pluginManagement>

    </build>

    Von der Logik her funktioniert die Klasse so:

    DocumentParserExecutable -> DocumentParserService -> Tika-core.jar -> Tika-Parser.jar -> diverse Parser Libraries je nach Documenten Typ.

    Ich habe mal die aktuellste module.xml mit drangehängt.

    Und hier ist noch der Aufruf in dem Script (ist noch nicht die finale Version):

    //!Beanshell

    import de.kernpunkt.firstspirit.module.documentparser.DocumentParserExecutable;

    Map map = new HashMap();

    map.put("documentInputStream", sc_stream);

    #! executable-class

    executable = new DocumentParserExecutable();

    executable.execute(map);

    Hast du da noch eine Idee?

    Danke und Grüße

    Olli

    0
  • Zendesk API User
    Author: mbergmann - 1/31/2019 9:22

    Hallo Olli,

    hast Du dir dieses Posting mal angesehen? Damit reicht der module scope. Der Trick ist, dass im entsprechenden "Script" die Notation

    #executable-class

    NAME_DER_PUBLIC_EXECUTABLE_LAUT_MODULE_XML

    benutzt wird. Es ist halt ein kleiner Umweg: Das (bzw. ein weiteres) Executable (z.B. ein "ParserProviderExecutable") macht nicht "selbst" die Arbeit, sondern ist erstmal nur dazu da, ein entsprechendes Objekt "herauszureichen" - in Deinem Fall eben den Parser - der muss dann selber kein Executable sein, sondern eine "normale" Klasse.

    Oder habe ich etwas übersehen warum das in Deinem Fall vielleicht nicht "passt"?

    Viele Grüße

    Michael

    0
  • Zendesk API User
    Author: oboeck - 2/12/2019 18:29

    Hey Michael,

    leider bleibt es dabei, auch mit der Umsetzung anhand deines Postings aus dem anderen Thread.

    Der sagt mir ständig, das er Klassen aus LIBs die aktuell auf module=scope stehen nicht finden kann.

    java.lang.NoClassDefFoundError: org/apache/tika/exception/TikaException

    In dem Objekt, also dem Parser, den ich aus der Executable rausgebe (wie in deinem Posting), wird halt dann die externe Lib die als module=scope eingebunden ist verwendet und dazu kann er dann die Klassen nicht finden.

    VG, Olli

    0

Please sign in to leave a comment.