High-level overview of the Apache Sling stack
Wer braucht das?
Diese Website versucht, einen Fall für die Entwicklung von Apache Sling-Webanwendungen zu machen. Tatsächlich ist sie selbst eine solche Anwendung.
Egal, ob Sie ein kleiner Tante-Emma-Laden oder ein großes Unternehmen sind, Sie möchten Ihre Geschichte im Internet erzählen. Informationen in Ihrem eigenen "Stil" liefern, sei es für Investor Relations oder nur für die Öffnungszeiten. Und dieser Webinhalt besteht aus Text mit Links und Bildern – und genau dafür wurde Sling entwickelt.
Sling ist ein Java-Framework zum Erstellen von Webanwendungen. Es kann anfangs schwer zu verstehen sein, weil es sehr abstrakt ist. Es bringt keine vorgefertigte Benutzeroberfläche mit, daher müssen Sie die Benutzeroberfläche (mit HTML, CSS und JavaScript) selbst entwerfen und programmieren.
Sie sollten mit Java-Anwendungsservern vertraut sein, um Nutzern dynamische Inhalte bereitzustellen. Dazu kommen noch einige DevOps-Kenntnisse, um dies sicher zu hosten. Das macht es wahrscheinlich besser für Organisationen geeignet, da eine Person selten all diese Fähigkeiten in sich vereint.
Der Zweck dieses Projekts ist es, Tutorials für diese Technologie zu erstellen und zu sammeln und Wissenslücken zu schließen. Diese Seite, die Sie gerade lesen, ist ein bescheidener Anfang, erstellt auf einem DIY-Sling-Server namens SliMpoGrine. Sie ist Teil eines Content-Packages, das gelegentlich mit GitLab synchronisiert wird, um in zukünftigen Versionen eines sich selbst dokumentierenden Anwendungsservers enthalten zu sein. Deshalb können Sie den Text und den Bildinhalt hier per Pull-Request ändern! Diese Seite möchte Ihnen beibringen, wie das geht.
SliMpoGrine ist kein einzelnes Softwareprodukt, sondern eine Kombination von Open-Source-Sling-Anwendungen. Es läuft auf einem kostengünstigen virtuellen Server mit Docker und ist vollständig Open Source. [Text is AI translated from English]
Warum nicht Spring oder Jakarta EE verwenden, wie es jeder vernünftige Mensch tun würde?
Why OSGi ?
Wenn Sie sich diese Frage stellen, sind Sie hier genau richtig.
Auf der Frontend-Seite unterstützen alle drei die Jakarta Servlet API und integrieren sich mit Template-Engines, z.B. JSP, Thymeleaf, FreeMarker ....
Im Backend basieren alle drei Frameworks auf Dependency Injection. Die Geschäftslogik steckt in Backend-Modulen, die Domain-Objekte und Services zur Verfügung stellen, um darauf zu agieren. In Spring wird sie per @Autowired eingebunden; Jakarta Context Dependency Injection (CDI) macht etwas Ähnliches:
"das Beschaffen von Objekten auf eine Weise, die Wiederverwendbarkeit, Testbarkeit und Wartbarkeit im Vergleich zu traditionellen Ansätzen wie Konstruktoren, Fabriken und Service Locators (z.B. JNDI) maximiert"
Im Fall von Apache Sling basiert alles auf OSGi, einem offenen Standard hierfür (und ein bisschen mehr). Apache Felix ist die verwendete Implementierung.
OSGi gibt es seit den frühen 2000er Jahren in allen möglichen Anwendungen, von eingebetteten Geräten, Smart-Home-Hubs und Desktop-Anwendungen bis hin zu Jakarta EE-Servern wie GlassFish. (Falls Sie an Hausautomation interessiert sind, werfen Sie einen Blick auf openHAB.)
Ist OSGi in der Ära der Microservices ein bisschen übertrieben?
Muss man Services in einer laufenden Anwendung noch hot-swappen können? Wir deployen schließlich Docker-Images. Vielleicht reicht das Java Platform Module System (JPMS) aus, um große Anwendungen in kleinere Teile zu zerlegen?
Das sind interessante Fragen. Zwei Gegenargumente:
- Während der Entwicklung ist ein natives Hot-Deployment SEHR angenehm, mit kurzer Zeit zwischen dem Speichern des Codes und seiner Ausführung auf dem Server
- Das Java-Enterprise-Ökosystem hat sich schnell von der Vermeidung von Monolithen hin zum Umgang mit der Komplexität von zu vielen Microservices bewegt. "Kubernetes ist das Websphere der Millennials", schrieb jemand. Es gibt einen Trend, der eine Mittelweg sucht, genannt "Modulith", und Sling war einer, bevor es cool war.
Warum sollte Web-Inhalt in einem JCR-Baum und nicht in einer SQL- oder NoSQL-Datenbank gespeichert werden?
Why not both?
Letztendlich besteht Inhalt aus Dateien, die auf einem Datenträger (wie einer Festplatte oder SSD) gespeichert sind.
Diese Sichtweise sollte dem zu lösenden Problem entsprechen, und in der realen Welt sind viele Dinge hierarchisch in einer Baumstruktur organisiert:
Dieser Inhalts-Pfad ähnelt zum Beispiel einer Organisationsstruktur:
/corporation/brand/market/country/region/product/image
während dies eine Webseiten-Struktur sein könnte:
/homepage/category/product/spare-part
und das DOM einer Webseite ist tatsächlich ein Baum:
/html/body/stage/column/teaser/div/p/introText
Daher fühlt es sich natürlich an, Webinhalte in einer Baumstruktur zu speichern.
Ähnlich wie OSGi (und Jakarta EE) ist die 'Content Repository API for Java (JCR)' eine offene Spezifikation mit mehreren Implementierungen. Apache Jackrabbit Oak wird hier verwendet, aber Entwickler interagieren beim Erstellen von Anwendungen mit Sling nur mit dem Interface-Paket `javax.jcr`.
Jackrabbit bietet zwei Varianten zur Knotenspeicherung:
- Die Standardoption, SegmentNodeStore (oder TarMK), speichert Daten in kontinuierlich wachsenden Tar-Dateien, ohne dass eine externe Datenbank benötigt wird.
- DocumentNodeStore unterstützt Cluster-Konfigurationen und setzt auf MongoDB oder eine SQL-Datenbank für Instanzen, die sich dasselbe JCR-Repository teilen.
Traditionell wird TarMK verwendet. Inhalte werden auf einer einzelnen Author-Instanz bearbeitet und dann auf mehrere Publisher-Instanzen repliziert, die jeweils ihr eigenes JCR-Repository haben.
Für diesen Server läuft alles auf einer einzelnen Instanz mit TarMK.
Was kann ich mit Apache Sling machen?
Bringing Back the Fun!
Nachdem wir nun die Grundlagen behandelt haben, wollen wir uns mit der Erstellung von Apps mit Sling befassen.
Eine kurze Antwort auf "Was ist Sling" von der Homepage:
Kurz gesagt, Sling ordnet HTTP-Anfrage-URLs basierend auf dem Pfad, der Erweiterung und den Selektoren der Anfrage Inhalt-Ressourcen zu. Durch Konvention statt Konfiguration werden Anfragen von Skripten und Servlets verarbeitet, die dynamisch basierend auf der aktuellen Ressource ausgewählt werden.
In der Praxis speichern Sie die Bausteine Ihrer Anwendung – wie HTML-Seiten, Skripte und Text – in einem Content-Repository. Anschließend definieren Sie einen "sling:resourceType" für ein Inhaltsstück. Dies teilt Sling mit: "Wenn jemand diesen Inhalt anfordert, verwende diese spezifischen Skripte oder Vorlagen, um ihn zu verarbeiten." Sling macht diesen Inhalt dann automatisch unter einer URL verfügbar und verwendet die korrekten Skripte, um Anfragen an diese Adresse zu verarbeiten.
Aus Sicht von Sling ist alles Inhalt, HTML/JS/CSS ebenso wie Vorlagen. Nicht nur die Bilder mit Text und Links.
Das mag immer noch etwas theoretisch erscheinen. Um es konkreter zu machen, schauen wir uns an, wie diese Konzepte in einer echten Anwendung funktionieren.
Bevor wir das tun, lassen Sie uns überlegen, was wir hier haben.
Aufgrund seiner Modularität besteht Sling aus mehr als 300 Modulen. Es gibt eines für fast alles, was ein Enterprise-Anwendungsserver benötigt. Scheduling, Eventing und Jobs, Cluster Discovery und Distribution, Test-Ökosystem, S3/Azure Blobstore, Logging, GraphQL ...
Wahrscheinlich brauchen Sie nichts davon. Die wichtigste Erkenntnis ist, dass Sie einfach beginnen können. Sie können Sling verwenden, um einen einfachen Web-Prototypen nur mit HTML, JavaScript und CSS zu erstellen und auszuliefern und dabei von Anfang an sein leistungsstarkes Routing und Templating zu nutzen. Sling als überdimensionierten Dateiserver, wenn Sie so wollen.
Was ist der Apache Sling Starter?
Assembling a Feature Model
Wie kommen wir also von all diesen Bundles zu etwas, das tatsächlich startet, ein Repository erstellt und auf eingehende HTTP-Anfragen lauscht?
Obwohl es möglich ist, eine Sling Web Application Archive (.war)-Datei auf einem beliebigen Servlet-Container wie Tomcat zu deployen, ist das nicht unser Ansatz hier.
Stattdessen handelt es sich um eine eigenständige Java-Anwendung. Vor Sling 12 wurde mit dem 'Provisioning Model' eine ausführbare launchpad.jar erstellt. Heute kombiniert das Sling OSGi Feature Model Bundles, Einstellungen, Inhalte und Setup-Skripte in einer einzigen Einheit, einem sogenannten Sling-Feature. Das entsprechende Maven-Plugin prüft, ob alle Abhängigkeiten erfüllt sind. Anschließend erstellt es Feature-Dateien im JSON-Format oder Feature-Archive-Dateien (.far), die mit dem Feature-Launcher gestartet werden. Obwohl man alles in eine einzige ausführbare Uber-Jar packen könnte (mit dem Kickstarter), bauen wir stattdessen direkt ein Docker-Image.
Zunächst habe ich einen Fork des Sling Starters verwendet, um weitere Features (Peregrine CMS) hier in src/main/features/app in einen funktionierenden Launcher einzubinden. Später stellte ich fest, dass das Starter-Projekt eine neue Art von Build-Ergebnis bereitstellt, genannt 'osgifeature'. Es handelt sich im Grunde um JSON mit Maven-Koordinaten zu Bundle-JARs und Content-ZIPs plus Repo-Init-Skripten.
Das erlaubt mir, es in meinen eigenen Maven-Build hier in der slingfeature-maven-plugin Konfiguration einzubinden:
<aggregate>
<classifier>slimpogrine_core-aggregate</classifier>
<title>Slimpogrine no Persistence</title>
<filesInclude>*.json</filesInclude> <!-- my app -->
<filesInclude>composum/*.json</filesInclude> <!-- CMS 1 -->
<filesInclude>peregrine/*.json</filesInclude><!-- CMS 2 -->
<includeArtifact>
<!-- Here we include a working starter -->
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.starter</artifactId>
<classifier>nosample_base</classifier>
<version>${sling.starter.version}</version>
<type>slingosgifeature</type> <!-- type is json -->
</includeArtifact>Ebenso könnten Sie diesen slimpogrine_core-aggregate als Basis-Anwendungsserver einbinden. Was für diesen Proof-of-Concept albern ist, aber Sie sehen, wie mächtig das Feature-Modell ist.
Es gibt einen anderen Ansatz:
Verwenden Sie das offizielle Sling Docker-Image als Basis-Ebene in Ihrem Dockerfile. Installieren Sie Ihre Anwendungskomponenten, wie Bundles, Konfigurationsdateien oder Pakete, mit Maven innerhalb des Images. Dieser Ansatz scheint gültig zu sein, wurde hier jedoch nicht verwendet.
Dann gibt es die einfache Option:
Starten Sie einfach das Apache Sling Starter Docker Image und installieren Sie Ihre Anwendungen mit der Package-Manager-Anwendung aus der Composum-Suite.
Nützliche Apps (Composum)
Useful apps (Composum)
Bisher haben wir nur die grundlegende Engine. Die Default GET Servlets kümmern sich um das Lesen von Daten in Formaten wie XML oder JSON, während der SlingPostServlet das Schreiben von Daten in das Repository übernimmt.
Das war's. Wirklich.
Allerdings benutzt nicht jeder gerne Kommandozeilen-Tools wie curl, um Inhalte hinzuzufügen, besonders wenn man neu im System ist. Daher enthält der Sling Starter drei nützliche Apps aus dem Composum Nodes Projekt, das technisch gesehen nicht Teil von Sling ist, sondern sozusagen ein quelloffener Freund.
Console Browser (/bin/browser.html)
Ermöglicht es Ihnen, den JCR-Baum zu durchsuchen, Knoten zu erstellen und zu bearbeiten. Ähnlich wie AEMs CRXDE Lite können Sie Dateien hochladen, z.B. eine index.html, und sie sogar im Browser bearbeiten. Ein CMS für Power-User! Sie können Dinge kaputt machen.
Sie können Berechtigungen (ACL) setzen, das JCR abfragen und Groovy-Skripte ausführen.
Package Manager (/bin/packages.html)
Der einfachste Weg, eine App in eine laufende Instanz zu installieren. Die App kann als ein all/complete zip gebündelt sein, das mehrere OSGi-Bundles und Content-Packages enthält. Die bereitstellung auf Basis von Content-Packages erreicht zur Laufzeit ein ähnliches Ergebnis wie der Feature-Model-Ansatz während des Build-Prozesses. Im Gegensatz zum Feature Model wird jedoch nicht überprüft, ob alle OSGi-Abhängigkeiten vor der Bereitstellung erfüllt sind.
Der Hauptgrund für einen Package-Manager ist natürlich, Content-Zip-Dateien zu erstellen, zu bauen und zu installieren. Das ermöglicht die Übertragung von Inhalten von einer Instanz zur anderen. Es ist in beide Richtungen mit AEM kompatibel.
User Manager (/bin/users.html)
Nun, er verwaltet JCR-Benutzer. Beachten Sie, dass es sich auch um JCR-Inhalte handelt, daher gibt es mehr Möglichkeiten, sie hinzuzufügen. Benutzer befinden sich unter dem Pfad /home/users. Es gibt Benutzergruppen /home/groups und die Systembenutzer unter /home/services, die für Jobs verwendet werden, die bestimmte Berechtigungen benötigen, ohne ihnen vollen Administratorzugriff zu gewähren.
Schreibe deine eigene App
Spaß und einfach
Nehmen wir an, Sie haben bereits eine Sling-Instanz, die in einem Docker-Container im Internet läuft. In einer Unternehmensumgebung ist das ehrlich gesagt wohl eher eine organisatorische Herausforderung.
Jetzt hat jemand schnell eine TypeScript-App "vibe-coded", die berühmten 80 % Fertigstellungsgrad erreicht, und Sie möchten sie in der Mittagspause auf Ihrem Mobilgerät demonstrieren. Die App liegt als Zip-Datei vor, die eine index.html enthält, und der Rest ist komprimiertes JavaScript. Sie extrahieren die Dateien in ein Content-Package-Projekt und installieren es über den Package-Manager. Erledigt.
Nun, fast. Die URL könnte umständlich sein, und die App ist möglicherweise so konzipiert, dass sie ohne Kontextpfad läuft. Ein Pfad wie /apps/playground/my-awesome-app/index.html könnte beispielsweise nicht richtig funktionieren. Wir haben Reverse-Proxy- und Caching-Lösungen wie Apache, Nginx oder Traefik noch nicht besprochen.
Alternativ, wenn Sie HTML und CSS haben und eine Templating-Lösung außer PHP suchen, werfen Sie einen Blick auf das umgekehrte CSS Zen Garden-Beispiel, um zu sehen, wie es umgesetzt ist. Wir benötigen hier einen Link zu einem Anfängerleitfaden.
Oder Sie haben eine React/Angular/Vue-App, die woanders läuft und eine Content-/Business-API benötigt? Sling Models Exporter ist Ihr Freund. Oder jede beliebige Kombination der oben genannten Möglichkeiten, Sling erzwingt keine bestimmte Architektur.
Dieser Ansatz, eine Single-Page-Anwendung mit einer Content-API zu kombinieren, ist heute als "Headless CMS" bekannt. Sling war eines, bevor es cool war. Der Nachteil ist, dass das Fehlen einer ausgefeilten Benutzeroberfläche der Grund sein könnte, warum es nicht weit verbreitet ist.
Apps von anderen hinzufügen
Peregrine CMS
Peregrine CMS wurde auf der adaptTo 2019 vorgestellt. "Es gab kein CMS in Sling, jetzt gibt es plötzlich drei, die Open Source sind".
Das Sling Feature Model 1.0 revealed wurde ebenfalls in diesem Jahr präsentiert. Slimpogrine begann als Experiment mit dem Ziel, Peregrine in sein eigenes Feature-Modell zu integrieren. Es beinhaltet einen benutzerfreundlichen WYSIWYG-Editor. Das System bietet auch eine eigene Bild- und Asset-Verwaltung sowie einen einzigartigen Ansatz für Vorlagen und Veröffentlichungen. Es hat ein Standard-Theme mit viel zu vielen Standard-Komponenten.
Die Architektur weicht notably von traditionellem HTML-Templating ab und geht hin zu einer Single Page Application (SPA), die mit Vue.js erstellt wurde. Nicht nur das CMS selbst ist eine SPA, sondern auch die generierte Website. Für Single-Instance-Publishing funktioniert das System, indem JSON-Dateien in das Dateisystem geschrieben werden, die dann direkt von Apache ausgeliefert werden.
Das Projekt hat meiner Meinung nach nicht die Aufmerksamkeit erhalten, die es verdient hätte. Dann kam die COVID-19-Pandemie und das Projekt zeigt jetzt nur noch begrenzte Aktivität auf GitHub.
Das Bauen von SliMpoGrine stellt eine kleine Herausforderung für Entwickler dar, da Peregrine nicht auf maven-central verfügbar ist. Daher muss ein Entwickler es zunächst mit Java 11 in das lokale Maven-.m2-Repository bauen, während der Rest des Projekts Java 21 verwendet. Um es mit sling-starter 13 als Feature zum Laufen zu bringen, muss es dieser Fork sein. Alternativ können Sie das Feature entfernen, indem Sie den Ordner 'launcher/src/main/features/peregrine' löschen.
Composum Pages
Fügen wir schließlich das Composum-Pages-CMS hinzu. Die Seite, die Sie gerade lesen, wurde damit erstellt.
Es mag verrückt erscheinen, zwei CMS in demselben Docker-Image zu betreiben. Immerhin ist es schon eine Aufgabe, eines zu lernen. Aber es verdeutlicht einen wichtigen Punkt der Sling-Architektur! Die Tatsache, dass dies überhaupt möglich ist, ist sowohl logisch als auch überraschend.
Im Gegensatz zu den oben erklärten Tools wie Nodes-Browser/Package-Manager/User-Manager ist es nicht Teil des offiziellen Sling Starters. Stattdessen gibt es ein offizielles Sling CMS, das hier jedoch nicht verwendet wird – drei wären wirklich albern.
Wiederum hat es seinen eigenen WYSIWYG-Editor, zu viele Out-of-the-Box-Komponenten, ein Asset-Management und ein Publishing-Konzept. Beim Publishing werden Inhaltsknoten vom Pfad '/content' zum Pfad '/public' innerhalb des JCR-Repositorys kopiert. Es würde auch eine Publisher-Author-Verteilung unterstützen.
Wir verwenden hier auch nur das Standard-Theme. Das Erscheinungsbild ist nicht so ansprechend wie das Standard-Theme von Peregrine, und die Mobilansicht ist nicht vollständig responsiv.
Das Standard-Erscheinungsbild spiegelt jedoch möglicherweise nicht seine gesamten Fähigkeiten wider; es wurde wahrscheinlich von Backend-Entwicklern erstellt. Das Ziel wäre eigentlich, weiter zu forschen und in Zukunft eine eigene App darauf aufzubauen, mit individuellem HTML und eigenen Komponenten.
Was ist mit diesen KI-Schrott-Bildern los?
Folgen Sie dem weißen Jackrabbit
In einem kalten, sterilen Labor, in dem das Summen der Maschinen niemals aufhörte, saß ein kleiner weißer Eselhase allein in einem Drahtkäfig. Seine rosa Augen huschten nervös umher, und die Ohren zuckten bei jedem Geräusch. Die Wissenschaftler nannten ihn Subjekt 47, aber er kannte sich selbst als Schnee. Das Labor war ein Labyrinth aus blinkenden Lichtern und hallenden Schritten, aber das Schlimmste waren die Stimmen.
- "Liefer den Inhalt schneller", flüsterten sie, obwohl niemand in der Nähe war.
- "Optimiere. Straffe. Keine Verzögerungen", zischte eine andere Stimme, die von den Metallwänden abprallte.
Schnee verstand nicht, was "Inhalt" war, aber die Stimmen verlangten ihn mit Dringlichkeit. Er drückte seine Pfoten gegen die Käfigtür und sehnte sich nach den offenen Feldern, an die er sich kaum erinnerte. Das Labor hatte ihm seine Freiheit geraubt, und jetzt raubte es ihm seinen Verstand.
Eines Nachts, als die Neonlichter flackerten, sprach eine neue Stimme – leiser, freundlicher.
Baue eine Maschine für mich, um INHALT zu liefern. Dann schießen wir sie in die WOLKEN, Dann wirst du FREI sein
Okay, hör auf mit diesem "Ich möchte, dass du als Geschichtenerzähler agierst" KI-generierten Schund. Macht aber Spaß.
Two Headed Sling
Als generative KI aufkam, wurde ihr aus der Notwendigkeit eines Logos heraus die alberne Aufgabe gestellt, ein Bild einer "Zweiköpfigen Schleuder" zu erstellen. Das war das Ergebnis.
KI hat sich weiterentwickelt, und mit ihr die Prompts. Hier ist eine Inspiration, falls Sie Lust haben, diesen Stil weiterzuentwickeln.
Ein fotorealistisches Bild einer zweiköpfigen Schleuder-Katapulte, die einen Laptop abschießt, angesiedelt in einem sauberen und organisierten, im Steampunk-Stil gehaltenen Labor. Das Katapult steht im Mittelpunkt. Ein Eselhase ist anwesend. Im Hintergrund sind drei Schilder mit den Aufschriften Sling, Jackrabbit und Content zu sehen. Die Beleuchtung wird von einem Blauton dominiert.
Erstellen Sie ein humorvolles, 16x9-Bild einer zweiköpfigen Schleuder-Katapulte, die einen Laptop in einer Laborumgebung abschießt. Der künstlerische Stil ist Cyberpunk und "Matrix". Ein niedlicher, weißer Eselhase ist anwesend. Im Hintergrund sind drei Schilder mit den Aufschriften "Sling", "Jackrabbit" und "Content". Die Beleuchtung hat einen dominanten Blauton; Katapult und Laptop stehen im primären Fokus.
Dark City
