Inhalt
Installation WildFly/Eclipse
Eclipse und WebTools-Plugin konfigurieren:
JBoss-KnowHow:
Installation JBoss/Eclipse
Benötigte Komponenten
Eclipse und WebTools-Plugin konfigurieren
Java 11 in Eclipse
Eclipse erkennt die installierten Java Runtimes. Falls wir (wie oben vorgeschlagen) das JDK 11 als Zipdatei heruntergeladen haben, weil ein neueres JDK bereits installiert sein könnte, dann muss man dieses händisch definieren:
Unter "Window" ==> "Preferences" ==> "Java" ==> "Installed JREs" wird ein neues zugefügt (der Screenshot zeigt bereits das Endergebnis):
Im ersten Schritt "Standard VM" wählen:
Im nächsten Schritt wählt man das Verzeichnis aus, in das das JDK entpackt wurde (oder das Installationsverzeichnis):
WildFly 32.0.x
In "Window" -> "Preferences..." gehen und links in der Übersicht den Punkt "Server" -> "Runtime Environments" wählen.
Über "Add..." einen neuen Server zufügen.
Im Bereich "JBoss Community" wählen einen Server vom Typ "WildFly 27+ Runtime"" aus.
Im nächsten Schritt als Runtime JRE ein Execution Environment "JavaSE-11" auswählen (sollte standardmäßig verfügbar sein, wenn Java 11 auf dem Rechner installiert ist)
und als "Home directory" das Wurzel-Verzeichnis des WildFly-Servers auswählen. Die Warnung im Kopfbereich ("This server type expects a version of 27.0 but the server directory is of version UNKNOWN.
This combination may not perform as expected.") wird ignoriert.
Eclipse-Tuning
Folgende Einstellungen empfehle ich, um Eclipse schneller und Resourcenschonender einzustellen:
Automatischen Build ausschalten
Die Option "Build Automatically" im Menü "Project" wird ausgeschaltet:
Das bedeutet dass man das Compilieren vor einem Deploy per Hand durch "Build Project" bzw. "Build All" anstoßen muss.
Rechtschreibprüfung abschalten
Die integrierte Rechtschreibprüfung (per Default sowieso nur englisches Wörterbuch) wird abgeschaltet:
Eclipse-Codeformatter
Damit der Quellcode zumindest innerhalb einer Projektgruppe bei allen gleich aussieht empfehle
ich die Codeformatierungs-Optionen von Eclipse zu vereinheitlichen. Dies geschieht über "Window" ->
"Preferences" -> "Java" -> "Code Style" -> "Formatter", wo man ein neues Profile zufügt.
Im folgenden die in meinen Beispielen verwendeten Einstellungen:
Eine Mischung aus Tabs und Leerzeichen sieht in einem anderen Editor meistens müllig aus,
deshalb nur Leerzeichen für Einrückung verwenden. Und mit nur 2 Leerzeichen sparen wir Platz.
Ich bevorzuge öffnende Klammern auf der gleichen Spalte wie die schließende Klammer, also
viele Zeilenumbrüche.
Passend zu den Zeilenumbrüchen vor öffnenden Klammern mag ich sie auch nach schließenden Klammern.
Die maximale Zeilenlänge bis zu einem vom CodeFormatter erzwungenen Zeilenumbruch
steht in neueren Eclipse-Versionen schon auf einem sinnvollen Default-Wert von "120":
Angewendet werden diese Einstellungen automatisch beim Tippen. Man kann aber auch nachträglich eine Datei formatieren,
indem man sie öffnet und im Editor-Contextmenü den Punkt "Source" - "Format" wählt:
Für die Formatierung von HTML-/JSP-Seiten finden wir die Formatierungseinstellungen unter "Window" -> "Preferences" ->
"Web" -> "HTML" -> "Editor". Auch hier werden Tabs abgeschaltet sowie die Zeilenlänge auf 120 Zeichen hochgedreht.
Javadoc
In den Preferences werden die JavaDoc-Warnungen eingeschaltet:
Projektstruktur
Die Struktur eines Projekts (im Beispiel das Stateless-Beispiel mit EJB-Projekt, Webprojekt
und ApplicationClient) sieht auf Festplatte so aus:
- Im Verzeichnis "StatelessClient\appClientModule" finden wir die Java-Quelldateien und im
Unterverzeichnis "META-INF" die Deskriptoren. In "StatelessClient\build\classes"
werden beim Build des Projekts die compilierten "class"-Dateien sowie benötigte Deployment-Deskriptoren
abgelegt.
- Dito für "StatelessEJB\ejbModule": hier liegen die Java-Quelldateien. Im
Unterverzeichnis könnten "META-INF" Deployment-Deskriptoren liegen. In "StatelessEJB\build\classes"
laden beim Build die "class"-Dateien und die Deployment-Deskriptoren.
- Beim Webprojekt liegen die Java-Dateien im Unterverzeichnis "src\main\java", während die Deskriptoren
und die JSP-Dateien im Verzeichnis "src\main\webapp" liegen. In "StatelessWeb\build\classes"
werden beim Build des Projekts die compilierten "class"-Dateien erstellt (hier werden allerdings keine
Dateien aus WEB-INF hinkopiert).
- In "Stateless\EarContent" liegen die Deployment-Deskriptoren der EAR-Anwendung (falls vorhanden).
Debugging
Zum Debuggen dürfen wir den JBoss nicht "normal" starten sondern im Debug-Modus (Rechtsklick auf den Server, "Debug"
wählen).
Im folgenden beziehe ich mich auf Klassen aus dem ersten Beispiel, "Stateless".
Wir setzen einen Breakpoint in der Methode doPost
des GeometricModelServlet
. Anschließend im Browser zu dieser URL navigieren:
http://localhost:8080/StatelessWeb/servlet/GeometricModelServlet.
Wenn wir alles richtig gemacht haben schiebt sich Eclipse in den Vordergrund, und wir werden gefragt ob wir
in die Debug-Perspective wechseln wollen (machen wir natürlich).
Stand 2024 kam hier eine Fehlermeldung "Source not found":
Auf "Edit Source Lookup Path..." klicken. Dort auf "Add..." klicken:
Den Typ "Java Project" wählen:
Und das Projekt "StatelessWeb" wählen:
In der Toolbar können wir jetzt Einzelschritte ausführen, in Funktionen springen oder aus einzelnen Funktionen hinausspringen. Über die Schaltfläche "Resume"
können wir die Verarbeitung bis zum nächsten Breakpoint weiterlaufen lassen.
Auf diese Weise können wir auch JSP-Seiten debuggen.
WildFly-Knowhow
Doku (hier für WildFly 32): https://docs.wildfly.org/32/
Dort findet sich z.B. ein "Getting Started Guide".
Verzeichnisstruktur
Ein WildFly-Paket besteht (unter anderem) aus diesen Verzeichnissen:
- "bin": enthält wichtige Scripte zum Serverstart und zur Administration. Beispiel:
- "standalone.bat": startet einen Server im Standalone-Modus. Über diese Datei müssten wir JBoss immer starten, wenn Eclipse
und das nicht abnehmen würde. Das Gegenstück zu dieser Datei ist "domain.bat": sie startet einen Server im Domain-Modus.
- "jboss-cli.bat": startet das "Command Line Interface" von JBoss, also die konsolenbasierte Administrations-"oberfläche".
- "appclient.bat": startet einen JavaEE-Application Client (jar-Datei innerhalb einer ear-Datei), siehe
Stateless-Beispiel.
Dazu wird ein Mini-JBoss-Umfeld gestartet, dessen Arbeitsbereich (Logdateien, Config, Temp-Verzeichnis) im
Verzeichnis "%JBOSS_HOME%\appclient" liegt
- "add-user.bat": kann Server-Benutzer anlegen - siehe weiter unten.
- "docs": enthält primär die XSD- und DTD-Dateien zu den von JBoss verwendeten Configdateien, darunter auch die XSDs des JavaEE-Umfelds.
- "standalone": enthält das Umfeld für einen JBoss im Standalone-Modus (für Details siehe nächster Abschnitt).
- "domain": enthält das Umfeld für einen JBoss im Domain-Modus. Für uns nicht relevant.
- "modules\system\layers\base": enthält im Prinzip alle Jar-Dateien, die JBoss benötigt: jede Jar-Datei liegt in einer Verzeichnisstruktur, die ihrem Package
entspricht. Jeder Package-Trenner wird zu einem Verzeichnis-Trenner.
Standalone/Domain
Siehe hier: https://docs.wildfly.org/32/Admin_Guide.html#Operating_modes
Stark vereinfacht: Im Domain-Modus gibt es einen zentralen Server ("Domain Controller"), bei dem sich weitere Server registrieren. Die Konfiguration
für alle Server wird über den Domain Controller gesteuert und abgeglichen. Dies ist nicht zu verwechseln mit einem Cluster, in dem mehrere Server
die gleiche Anwendungs-Funktionalität anbieten und Clientanfragen an unterschiedliche Server verteilt werden - dies ist in Domain- und Standalone-Modus
möglich.
Im Rahmen dieser Dokumentationen konzentrieren wir uns auf einen Standalone-Server.
Dieser befindet sich im Verzeichnis "%JBOSS_HOME%\standalone" und hat folgende Unterverzeichnisse:
- "configuration": Hier findet sich die Server-Konfiguration ("standalone.xml" ist der Default, die anderen "standalone-xx.xml"-Dateien
biete andere Konfigurationsprofile und müssen explizit beim Serverstart angegeben werden, um genutzt zu werden.
Die Dateien "mgmt-users.properties" und "application-users.properties" enthalten Benutzer, die mittels "%JBOSS_HOME%\add-user.bat" angelegt wurden.
- "data": enthält Laufzeitdaten des Servers, z.B. Transaktionen oder Timer
- "deployments": hier können im Standalone-Server Anwendungen abgelegt werden, die in den Server eingespielt werden sollen.
Im Domain-Modus gibt es dieses Verzeichnis nicht. Mehr zum Deploy von Anwendungen weiter unten.
- "log": Protokolldateien des Servers. "boot.log" wird beim Serverstart geschrieben, "server.log" enthält genau die Ausgaben, die wir auch
in der Konsole sehen.
- "tmp": enthält die temporären Dateien des Servers. Im Verzeichnis "vfs" (Virtual File System) finden sich in Unterverzeichnissen z.B. Dateien, die als Archiv
ins "deployments"-Verzeichnis kopiert wurden und im "vfs"-Verzeichnis entpackt wurden. In "work" finden sich Daten des integrierten Webservers, siehe unten.
JBoss starten/stoppen
Ganz trivial:
Starten: "%JBOSS_HOME%\bin\standalone.bat" ausführen (startet Server im Standalone-Modus)
Vorher sollten die Umgebungsvariablen "JAVA_HOME" und "WILDFLY_HOME" gesetzt werden und (falls nötig) die Java Runtime dem "PATH" zugefügt werden, falls es auf dem Rechner mehr als eine Java Runtime gibt:
set PATH=C:\Temp\jdk-11.0.23\bin;%PATH%
set JAVA_HOME=C:\Temp\jdk-11.0.23
set JBOSS_HOME=C:\Temp\wildfly-32.0.0.Final
Stoppen: In dem beim Start aufgehenden Konsolenfenster "Strg+C" drücken. Man kann den Server auch über die diversen Verwaltungskonsolen
stoppen, siehe weiter unten.
Alternativ kann auch das Powershell-Script "standalone.ps1" verwendet werden.
Command Line Interface (CLI)
Das "Command Line Interface" (kurz: CLI) ist eine der Verwaltungsmöglichkeiten für einen JBoss-Server.
Siehe https://docs.wildfly.org/32/Admin_Guide.html#Command_Line_Interface
Man startet es durch Ausführen von %JBOSS_HOME%\bin\jboss-cli.bat. Es bietet sich folgenden Ausgabe:
Mittels des Befehls "connect" (bzw. "connect localhost:9990" als Beispiel für die Angabe von Server und Port - das sind auch die Defaults)
baut man eine Verbindung zum JBoss-Server auf:
Mehr Beispiele für die Anwendung der CLI kommen später.
Hier nur soviel:
- "quit" beendet die laufende Sitzung.
- "shutdown" stoppt den JBoss-Server
Hinweis: an sehr vielen Stellen wird Tab Completion unterstützt. Nicht nur Befehle sind erweiterbar, sondern auch für die Argumente gibt
es die Vorschläge und Vervollständigung.
Es gibt auch eine GUI-Variante der Konsole (siehe
https://developer.jboss.org/docs/DOC-17457 und https://developer.jboss.org/docs/DOC-17862 - beides sehr alte Artikel,
aber es gibt keine Verweise auf dieses Feature in der aktuellen Doku).
Diese wird gestartet mittels "jboss-cli.bat --gui":
Web-Console
Eine zweite Verwaltungsmöglichkeit ist die Webkonsole. Diese erreicht man über http://localhost:8080 (dort
auf den Link "Administration Console" klicken) bzw. direkt über http://localhost:9990/console
Beim ersten Aufruf wird nur eine Anmeldemaske angezeigt, und nach ein paar Fehlversuchen oder "Abbrechen" wird eine Fehlerseite kommen, die allerdings nicht wirklich viele Infos liefert:
Die dort beschriebene Variante bezüglich des "$local"-Users funktioniert aber scheinbar nicht wie erwartet.
Also legt man einen neuen User an:
- Man ruft das Script %JBOSS_HOME%\bin\add-user.bat" auf
- Man wählt Option "a) Management User (mgmt-users.properties)"
- Im nächsten Schritt wird automatisch das Realm als "ManagementRealm" vorbelegt.
- Jetzt gibt man einen Usernamen an. In meinem Beispiel habe ich "admin" angegeben. Da dieser bereits deaktiviert vorliegt (siehe "mgmt-users.properties"), wird er im Rahmen des Passwort setzen außerdem aktiviert.
- Im nächsten Schritt ist ein Passwort gefragt. Hier gibt es ziemlich strenge Validierungsregeln, die ein zu einfaches Passwort
verbieten. Ohne Anspruch auf Vollständigkeit: das Passwort muss mind. 8 Zeichen lang sein. Es muss mindestens ein nicht-alphanumerisches
Symbol enthalten.
Wichtig: dieses Passwort irgendwo notieren - wir werden es später noch benötigen!
- Bei der Frage "What groups do you want this user to belong to?" geben wir nichts an.
Jetzt haben wir es geschafft. Hier alle Schritte als Screenshot:
Der User wurde (wie man schon dem Screenshot entnehmen kann) in der Datei "%JBOSS_HOME%\standalone\configuration\mgmt-users.properties" aktiviert und ein Passwort wurde gesetzt.
Das Passwort in der Datei ist gehasht.
Jetzt endlich können wir uns in der Webkonsole anmelden:
Unten rechts findet sich im Aufklappmenü unter "Tools" der Punkt "Management Model".
Hier sehen wir in einer Baumstruktur die Konfiguration aus "standalone.xml" sowie Informationen über aktuell deployte Anwendungen.
(das Bild ist nachbearbeitet - die Liste der Attribute ist ein Stück nach unten gescrollt, um ein paar relevante Informationen zu zeigen).
Im Beispiel ist der Bereich aufgeklappt, der die Datenbankverbindungen enthält. Auf der rechten Seite sieht man
drei Karteireiter, darunter eine Liste der Attribute und Operationen, die dieses Objekt bietet und die man per CLI abrufen kann.
Der Screenshot zeigt den Karteireiter "Data", auf dem die aktuellen Property-Werte dieses Objekts ausgegeben werden.
Auf die Attribute kann man auch per CLI zugreifen. Beispiel: Auslesen des Attributs "connection-url":
[standalone@localhost:9990 /] /subsystem=datasources/data-source=ExampleDS:read-attribute(name=connection-url)
{
"outcome" => "success",
"result" => "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
}
Und hier ein Screenshot, der eine deployte Anwendung (das Stateless-Beispiel) zeigt:
Viel mehr als den "Logout"-Button rechts unten zu nutzen können wir allerdings bisher nicht tun - mehr später ;-)
Deploy
Für das Deployen einer Anwendung gibt es mehrere Möglichkeiten:
Deploy ins "deployments"-Verzeichnis
Diese Variante ist nur in einen standalone-JBoss verfügbar. Der "domain"-Server bietet diese Möglichkeit nicht.
Die einfachste Art des Deployments ist es, ein Archiv (Ear, war, jar) in dieses Verzeichnis zu kopieren. JBoss
wird die Datei erkennen und automatisch deployen. Umgekehrt führt ein Löschen zu einem Undeploy, und ein Überschreiben durch
eine neuere Version zu einem Redeploy.
Wenn man ein "Exploded Deployment" durchführen will (also statt einer Archivdatei die entpackte Verzeichnisstruktur, wobei das
oberste Verzeichnis exakt so benannt ist wie eine Archivdatei, z.B. "Stateless.ear" als Verzeichnis!), dann führt JBoss kein automatisches
Deploy durch (Grund ist: der Server kann nicht erkennen, wann das hinkopieren der Daten abgeschlossen ist, und würde eventuell
eine halbe Anwendung deployen). Stattdessen muss man das Deployment über "Marker files" anstoßen. Diese haben den gleichen Namen
wie die zu deployende Anwendung (inklusive ear/war/jar-Zusatz), über ihre Endung wird die durchzuführende Aktion gesteuert.
Siehe https://docs.wildfly.org/32/Admin_Guide.html#deploying-using-the-deployment-scanner
oder auch die "README.txt" im "deployments"-Verzeichnis.
Beispiel: "Stateless.ear.dodeploy" startet das Deploy der Anwendung "Stateless.ear" (die natürlich schon vorher im "deployments"-Verzeichnis liegen muss).
Der Server löscht diese Datei, sobald das Deploy gestartet wurde, und schreibt während des Vorgangs diverse Status-Dateien:
"Stateless.ear.isdeploying" ist das Kennzeichen für "Deployment läuft gerade". Im Erfolgsfall wird diese Datei durch "Stateless.ear.deployed"
ersetzt. Löscht man diese Datei, erfolgt automatisch ein Undeploy. Im Fehlerfall entsteht "Stateless.ear.failed", die außerdem
eine Deployment-Fehlermeldung enthält. Löscht man diese Datei, erfolgt ebenfalls ein Undeploy.
Über eine Datei "Stateless.ear.skipdeploy" kann man das Deploy der Anwendung unterdrücken.
Deploy über CLI
Das Deploy einer Anwendung erfolgt so:
[standalone@localhost:9990 /] deploy c:\temp\Stateless.ear
Hinweis: auch bei Eingabe des Pfads hat man mittels "Tab" eine Komplettierung der Eingabe zur Verfügung, wie von Windows- oder Linux-Kommandozeile
bekannt.
Die deployte Anwendung findet sich auf dem Server wieder in einem Verzeichnis "%JBOSS_HOME%\standalone\tmp\vfs\deployment<zufallswert>"
Außerdem trägt JBoss die Anwendung in "standalone.xml" ein:
<deployments>
<deployment name="Stateless.ear" runtime-name="Stateless.ear">
<content sha1="2a62e331dff5c46922429a1269da21f185f9d7b8"/>
</deployment>
</deployments>
Der Wert "content" führt vermutlich zu dem eigentlichen Pfad von "Stateless.ear", allerdings gehasht.
Die originale EAR-Datei scheint in "%JBOSS_HOME%\standalone\tmp\vfs\temp<zufallswert>\content-<zufallswert>"
zu liegen. In diesem Verzeichnis gibt es eine Datei "content" - dies ist die umbenannte Datei "Stateless.ear".
Aus diesem Verzeichnis wird die Anwendung bei einem Server-Neustart geholt und die Inhalte in ein neues "...tmp\vfs\deployment..." gelegt.
Das Undeploy erfolgt so:
[standalone@localhost:9990 /] undeploy Stateless.ear
Hier wird nur der Name der Anwendung angegeben, ohne Pfad.
Deploy über Webconsole
Es gibt zwei Wege zum Deployment: auf der "Homepage"-Seite gibt es im Bereich "Deployments" neben dem Info-Dropdown "Deploy an application", einen Button "Start".
Alternativ kann man oben auf den Karteireiter "Deployments" klicken.
Auf der Seite "Deployments" klickt man auf den "+"-Button und wählt "Upload Deployment":
Es öffnet sich ein Assistent, in dem man die Datei auswählt.
Im nächsten Schritt (Name der Anwendung) kann man alles auf den Defaults belassen. Dort gibt es auch einen Schieber, mit dem man die Anwendung direkt aktivieren kann (per Default eingeschaltet):
Generierte JSP-Java-Klassen
Zu JSP-Seiten generiert der in den JBoss integrierte Webserver (der Undertow-Webserver, eine
JBoss-Eigenentwicklung) Java-Dateien, diese wiederum werden ganz normal compiliert. Die generierten Java-Dateien findet man in
"WILDFLY_HOME%\standalone\tmp\(name der Web-Applikation)\org\apache\jsp" (z.B. "standalone\tmp\Stateless.ear.StatelessWeb.war\org\apache\jsp").
Ein Blick in diese Dateien ist bei Compilefehlern in der JSP-Seite eventuell nötig, wobei in den meisten Fällen die fehlerhaften Zeile
der JSP-Datei angegeben wird. Nur bei sehr schweren Syntax-Fehlern kann es nötig sein, einen Blick in die generierte Java-Datei zu werden.
JNDIView
Die JNDIView listet alle Einträge im Server-JNDI auf, darunter finden sich auch unsere eigenen Beans.
Webconsole
Über die Webconsole ist die "JNDIView" simpel zu erreichen: über den Karteireiter "Runtime" findet man links
eine Liste der Server. Hier steht im Falle eines Standalone-Servers natürlich nur ein Eintrag. Diesen klickt man an. Danach öffnet sich in einer
zweiten Spalte eine Liste der Subsysteme. Dort wählt man "JNDI" aus und klickt auf "View":
Auf der neuen Seite finden sich die JNDI-Einträge - im Beispiel für das Stateless-Beispiel:
CLI
Der benötigte Befehl ist:
[standalone@localhost:9990 /] /subsystem=naming:jndi-view
Das Ergebnis ist relativ unübersichtlich, enthält aber die gleichen Informationen wie die Webconsole:
JNDI-Namen
Der JakartaEE-Standard (https://eclipse-ee4j.github.io/jakartaee-tutorial/#portable-jndi-syntax
bzw. https://jakarta.ee/learn/docs/jakartaee-tutorial/current/entbeans/ejb-intro/ejb-intro.html#_portable_jndi_syntax)
definiert, wie JNDI-Namen aufgebaut sind. Anmerkung: in früheren JavaEE-Versionen war es dem jeweiligen Implementierer überlassen,
wie ein Name auszusehen hat. Mit JavaEE6 wurde dies standardisiert.
Es gibt drei Bereiche ("JNDI Namespaces"), in denen JNDI-Einträge gebunden werden können:
- Global: beginnt ein JNDI-Name mit "java:global", dann liegt dieser Eintrag global im Server vor und kann von allen Komponenten (die auf dem
Server laufen oder auch von außen darauf zugreifen) abgerufen werden. Die Syntax ist:
java:global[/application name]/module name/enterprise bean name[/interface name]
Der optionale "application name" (und der "/" davor) ist nötig, wenn die deployte Anwendung Teil eines EAR ist. Ansonsten wird dieser Teil weggelassen.
Der "interface name" ist ebenfalls optional: will man auf eine EJB über ein Local oder Remote Interface zugreifen, steckt hier der Name
des Interfaces. Bei WildFly ist dies per Default der volle Name des Interfaces ("Package.Interface"). Im Falle einer "no interface view"
wird dieser Teil weggelassen (siehe Abschnitt im Stateful-Beispiel).
- Modul: beginnt ein JNDI-Name mit "java:module", dann liegt dieser Eintrag nur innerhalb des Moduls (z.B. ein EJB-JAR oder ein Web-Modul) vor
und kann von allen Komponenten in diesem Modul abgerufen werden, aber nicht von Komponenten außerhalb. Die Syntax ist:
java:module/enterprise bean name/[interface name]
Bei einem Webmodul erlaubt dies nur Zugriff auf EJBs, die in der Webanwendung definiert sind. Ist das Webmodul Teil einer EAR-Datei, dann könnte
man nicht auf EJBs zugreifen, die in einem separaten EJB-JAR liegen.
- Anwendung: beginnt ein JNDI-Name mit "java:app", dann liegt dieser Eintrag nur innerhalb der Anwendung (also einer EAR-Datei) vor
und kann von allen Modulen in dieser Anwendung abgerufen werden, aber nicht von Komponenten außerhalb. Die Syntax ist:
java:app[/module name]/enterprise bean name[/interface name]
Hier kann eine Webmodul auf EJBs zugreifen, die in einer EJB-JAR liegen, sofern beide Module in einer EAR-Datei gebündelt sind.
- Komponente: jede Komponente kann außerdem einen privaten Namespace definieren. Ein Beispiel hierfür ist die Deklaration einer EJB-Referenz in "web.xml" oder
"application-client.xml", die an einen JNDI-Eintrag gebunden ist. Was eine Komponente ist, ist unterschiedlich:
Eine Webanwendung oder ein Application Client
zählen als eine einzige Komponente, so dass alle im Deploymentdeskriptor deklarieren "java:comp"-Einträge allen Klassen im Modul zur Verfügung stehen.
In den Deployment Deskriptoren sind die Elemente "ejb-ref" und "ejb-local-ref" globale Elemente.
In einem EJB-JAR zählt jede EJB als Komponente und hat deshalb ihren eigenen "java:comp"-Namespace. Die Elemente "ejb-ref" und "ejb-local-ref"
sind deshalb Kinder des "enterprise-beans/session"-Elements.
Siehe http://stackoverflow.com/questions/7458114/what-is-the-relationship-between-javacomp-env-and-javaglobal
In der Verwendung wird beim Lookup immer dieser JNDI Context vor den Namen gestellt: "java:comp/env/".
In der Deklaration darf man "java:comp/env/" allerdings nicht angeben, da er implizit gilt.
- JBoss-Erweiterung: "java:jboss/exported": in diesem Namespace werden Remote Interfaces gebunden, auf die über Non-JavaEE-Anwendungen
über das Verfahren "jboss-remote-naming" zugegriffen wird, siehe Zugriff auf Stateless Session Bean aus Java-Anwendung-
Beispiel.
- JBoss-Erweiterung: "ejb:": in diesem Namespace werden Remote Interfaces gebunden, auf die über Non-JavaEE-Anwendungen
über das Verfahren "JBoss EJB client" zugegriffen wird, siehe Zugriff auf Stateless Session Bean aus Java-Anwendung-
Beispiel. Dieser Namespace gilt wohl nur in EJB-Clients.
- JBoss-Erweiterung: "java:jboss": diesen Namespace habe ich nur in der Server-Konfiguration vorgefunden: hier werden z.B.
DataSources gebunden ("java:jboss/datasources/ExampleDS", für die Verwendung in der Anwendung siehe
Kuchen-Beispiel)
Deployen wir eine Anwendung, sehen wir, dass JBoss JNDI-Bindings für alle Bereiche erzeugt (im folgenden für das Stateless-Beispiel):
20:44:32,875 INFO [org.jboss.as.ejb3.deployment] (MSC service thread 1-6) WFLYEJB0473: JNDI bindings for session bean named 'GeometricModelBean' in deployment unit 'subdeployment "StatelessEJB.jar" of deployment "Stateless.ear"' are as follows:
java:global/Stateless/StatelessEJB/GeometricModelBean!de.hsrm.jakartaee.knauf.stateless.GeometricModelRemote
java:app/StatelessEJB/GeometricModelBean!de.hsrm.jakartaee.knauf.stateless.GeometricModelRemote
java:module/GeometricModelBean!de.hsrm.jakartaee.knauf.stateless.GeometricModelRemote
java:jboss/exported/Stateless/StatelessEJB/GeometricModelBean!de.hsrm.jakartaee.knauf.stateless.GeometricModelRemote
ejb:Stateless/StatelessEJB/GeometricModelBean!de.hsrm.jakartaee.knauf.stateless.GeometricModelRemote
java:global/Stateless/StatelessEJB/GeometricModelBean!de.hsrm.jakartaee.knauf.stateless.GeometricModelLocal
java:app/StatelessEJB/GeometricModelBean!de.hsrm.jakartaee.knauf.stateless.GeometricModelLocal
java:module/GeometricModelBean!de.hsrm.jakartaee.knauf.stateless.GeometricModelLocal
Entsprechend können wir im Stateless-Beispiel in der JSP "GeometricModel.jsp" einen Lookup auf die Einträge in "java:global" und in "java:app" durchführen,
aber nicht auf "java:module".
Logging
In allen Beispielen wird das Logging mittels der Klassen des Packages java.util.logging
verwendet. Im Code sieht das so aus:
Auf Klassenebene wird ein Logger deklariert (Codefragmente aus dem Stateless-Beispiel):
protected static final Logger logger = Logger.getLogger(GeometricModelBean.class.getName());
Die Logausgabe erfolgt so:
logger.info("computeCuboidVolume mit a = " + a + ", b = " + b + ", c = " + c);
JBoss ist in Sachen Logging die eierlegende Wollmilchsau und unterstützt über den "JBoss Log Manager" so ziemlich alle relevanten
Logging-Frameworks:
Quelle: https://www.wildfly.org/guides/application-logging
WildFly-Doku zur Logging-Konfiguration:
https://docs.wildfly.org/32/Admin_Guide.html#Logging
JBoss Logging wird konfiguriert über die Datei "%JBOSS_HOME%\standalone\configuration\standalone.xml". Diese enthält einen Abschnitt "subsystem xmlns="urn:jboss:domain:logging:8.0"
(die Versionsnummer kann sich je nach WildFly-Version ändern).
Für mein Stateless-Beispiel sieht die Config so aus:
<subsystem xmlns="urn:jboss:domain:logging:8.0">
<console-handler name="CONSOLE">
<level name="INFO"/>
<formatter>
<named-formatter name="COLOR-PATTERN"/>
</formatter>
</console-handler>
<file-handler name="StatelessFILE" autoflush="true">
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
<file relative-to="jboss.server.log.dir" path="stateless.log"/>
<append value="true"/>
</file-handler>
<periodic-rotating-file-handler name="FILE" autoflush="true">
<formatter>
<named-formatter name="PATTERN"/>
</formatter>
<file relative-to="jboss.server.log.dir" path="server.log"/>
<suffix value=".yyyy-MM-dd"/>
<append value="true"/>
</periodic-rotating-file-handler>
<logger category="com.arjuna">
<level name="WARN"/>
</logger>
<logger category="com.networknt.schema">
<level name="WARN"/>
</logger>
<logger category="io.jaegertracing.Configuration">
<level name="WARN"/>
</logger>
<logger category="org.jboss.as.config">
<level name="DEBUG"/>
</logger>
<logger category="sun.rmi">
<level name="WARN"/>
</logger>
<logger category="de.hsrm.jakartaee.knauf.stateless" use-parent-handlers="false">
<level name="INFO"/>
<handlers>
<handler name="StatelessFILE"/>
</handlers>
</logger>
<root-logger>
<level name="INFO"/>
<handlers>
<handler name="CONSOLE"/>
<handler name="FILE"/>
</handlers>
</root-logger>
<formatter name="PATTERN">
<pattern-formatter pattern="%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
</formatter>
<formatter name="COLOR-PATTERN">
<pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
</formatter>
</subsystem>
Fett markiert sind hier die beiden Abschnitten, die für das Stateless-Beispiel relevant sind:
- Zuerst wird ein Handler deklariert. Dieser kümmert sich darum, was mit Logeinträgen passiert.
Ein "console-handler" gibt sie auf der Konsole aus.
Ein "periodic-rotating-file-handler" schreibt sie in eine Datei, deren Name sich nach einem
bestimmten Muster aus dem aktuellen Datum aufbaut und entsprechend bei jedem Datumswechsel in eine neue Datei geschrieben wird.
Genauer: die aktuellen Logausgaben landen immer in der gleichen Datei (hier: "server.log"), beim Datumswechsel wird diese
Datei umbenannt in eine Datei mit Datumsstempel.
Und der von mir benutzte "file-handler" ist die vereinfachte Variante: hier wird in eine Datei festen Namens geschrieben.
- Teil 2 der Konfiguration ist eine Filterung der Logeinträge, die im Log-Manager ankommen. Dies geschieht über das
Element "logger". Das Element "category" gibt ein Package an: dieser Logger verarbeitet nur Logeinträge, die von Methoden
dieses Packages geschrieben wurden.
Ein Logger kann außerdem "handler" referenzieren: seine Logausgaben landen werden alle auf diesem Handler geschrieben.
Dadurch kann loggt obiges Beispiel alle Einträge des Package "de.hsrm.jakartaee.knauf.stateless" in eine separate
Logdatei.
Außerdem laufen alle Logeinträge über den "root-logger". D.h. meine Stateless-Logeinträge würde auch auf die Serverkonsole und in
"server.log" geschrieben. Will man diese verhindern, dann setzt man im "logger" das Element "use-parent-handlers" auf "false" - dadurch
werden Logeinträge, die in den Filter dieses Logger fallen, nicht an den "root-logger" weitergereicht.
Logger per CLI konfigurieren
Dies basiert auf https://docs.wildfly.org/32/Admin_Guide.html#Logging_How_To:
Zuerst wird der Handler definiert:
[standalone@localhost:9990 /] /subsystem=logging/file-handler=StatelessFILE:add(file={"relative-to"=>"jboss.server.log.dir", "path"=>"stateless.log"}, formatter="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"
{"outcome" => "success"}
Die zweite Zeile gibt das zu erwartende Ergebnis an.
Der Ausdruck wirkt "schrecklich", aber dank Tab-Completion kommt man meistens ziemlich gut zurecht.
Im zweiten Schritt wird der Logger deklariert:
[standalone@localhost:9990 /] /subsystem=logging/logger=de.hsrm.jakartaee.knauf.stateless:add(use-parent-handlers=false,handlers=[StatelessFILE],level=INFO)
{"outcome" => "success"}
Das Löschen des Loggers geht analog:
[standalone@localhost:9990 /] /subsystem=logging/logger=de.hsrm.jakartaee.knauf.stateless:remove
{"outcome" => "success"}
[standalone@localhost:9990 /] /subsystem=logging/file-handler=StatelessFILE:remove
{"outcome" => "success"}
Stand 01.06.2024
Historie:
01.06.2024: Erstellt auf Basis der JavaEE8-Doku, angepasst an Eclipse 2024-03, WildFly 32 etc.