Update Wiki for 1.4.0

2026-08-22 15:46:50 +02:00
parent 9b492fdac8
commit 3565983496
18 changed files with 539 additions and 48 deletions
+7 -2
@@ -24,7 +24,7 @@ romexis-common/
- Firebird-Clientbibliotheken und -Werkzeuge
- gemeinsame Betriebssystempakete
- native Chilkat-Bibliothek und JAR
- `RomexisPropertyAgent.jar`
- `RomexisPropertyAgent.jar` mit eingebetteten RxCr2- und OptionPane-Transformern
- Sicherheitsaktualisierungen
Die aufwendigen Native-/Java-Artefakte werden dadurch einmal pro Architektur statt einmal pro Romexis-Version gebaut.
@@ -39,11 +39,16 @@ Die aufwendigen Native-/Java-Artefakte werden dadurch einmal pro Architektur sta
- Xvfb, Openbox und xcompmgr
- x11vnc und noVNC/websockify
- GTK-/Mesa-/OpenGL-Abhängigkeiten
- Chilkat und `RomexisPropertyAgent.jar`
- Chilkat und `RomexisPropertyAgent.jar` einschließlich Java-17-Swing-Lifecycle-Null-Guard
- die aus `romexis-common/dxservice_dummy.c` gebaute DxService-Kompatibilitätsbibliothek
Admin und Client installieren bzw. kompilieren diese Abhängigkeiten daher nicht erneut für jede Romexis-Version.
Das Agent-JAR enthält ASM und `RomexisOptionPaneUIPatch.class`; in den finalen
Containern ist kein separates ASM-Artefakt erforderlich. Der Patch transformiert
nur die betroffene In-Memory-Listenerklasse und schreibt das proprietäre
Romexis-JAR auf dem Datenträger nicht um.
---
## Architekturspezifische Tags
+7 -2
@@ -24,7 +24,7 @@ romexis-common/
- Firebird client libraries and tools
- common OS packages
- Chilkat native library and JAR
- `RomexisPropertyAgent.jar`
- `RomexisPropertyAgent.jar` with embedded RxCr2 and OptionPane transformers
- security updates
The expensive native/Java artifacts are therefore built once per architecture instead of once per Romexis version.
@@ -39,11 +39,16 @@ The expensive native/Java artifacts are therefore built once per architecture in
- Xvfb, Openbox and xcompmgr
- x11vnc and noVNC/websockify
- GTK/Mesa/OpenGL dependencies
- Chilkat and `RomexisPropertyAgent.jar`
- Chilkat and `RomexisPropertyAgent.jar`, including the Java 17 Swing lifecycle null guard
- the DxService compatibility library built from `romexis-common/dxservice_dummy.c`
Admin and Client therefore do not repeatedly install or compile these dependencies for every Romexis version.
The agent JAR embeds ASM and `RomexisOptionPaneUIPatch.class`; no separate ASM
artifact is required in the final containers. The patch transforms only the
affected in-memory listener class and does not rewrite the proprietary Romexis
JAR on disk.
---
## Architecture-Specific Tags
+3 -3
@@ -66,15 +66,15 @@ Er erzeugt:
- Firebird-Clientbibliotheken und -Werkzeuge
- Betriebssystemabhängigkeiten
- Chilkat
- Java Property Agent
- Java Property Agent mit eingebetteten RxCr2- und RomexisOptionPaneUI-Runtime-Patches
### GUI-Runtime-Build
`romexis-gui-runtime` enthält den von Admin und Client gemeinsam verwendeten architekturspezifischen Grafik-Stack: Java 17/OpenJFX, X11/noVNC, Mesa/GTK, Chilkat, PropertyAgent und die DxService-Kompatibilitätsbibliothek.
`romexis-gui-runtime` enthält den von Admin und Client gemeinsam verwendeten architekturspezifischen Grafik-Stack: Java 17/OpenJFX, X11/noVNC, Mesa/GTK, Chilkat, PropertyAgent mit Java-17-OptionPane-Null-Guard und die DxService-Kompatibilitätsbibliothek.
### Gemeinsame Runtime-Quellen
`romexis-common/` ist der zentrale Quellort für `RomexisPropertyAgent.java`, die Chilkat-Patch-Quelle und `dxservice_dummy.c`. Diese Quellen werden in die passenden Runtime-Images kompiliert, statt in Verzeichnissen finaler Images dupliziert zu werden.
`romexis-common/` ist der zentrale Quellort für `RomexisPropertyAgent.java`, `RomexisOptionPaneUIPatch.java`, den RxCr2-Ersatz und `dxservice_dummy.c`. Der Agent-Build bettet ASM und beide gezielten Runtime-Patches in `RomexisPropertyAgent.jar` ein. Diese Quellen werden in die passenden Runtime-Images kompiliert, statt in Verzeichnissen finaler Images dupliziert zu werden.
### Server-Image-Build
+3 -3
@@ -66,15 +66,15 @@ It produces:
- Firebird client libraries and tools
- OS dependencies
- Chilkat
- Java property agent
- Java property agent with embedded RxCr2 and RomexisOptionPaneUI runtime patches
### GUI runtime build
`romexis-gui-runtime` contains the architecture-specific graphical stack shared by Admin and Client: Java 17/OpenJFX, X11/noVNC, Mesa/GTK, Chilkat, PropertyAgent and the DxService compatibility library.
`romexis-gui-runtime` contains the architecture-specific graphical stack shared by Admin and Client: Java 17/OpenJFX, X11/noVNC, Mesa/GTK, Chilkat, PropertyAgent with the Java 17 OptionPane null guard, and the DxService compatibility library.
### Shared runtime sources
`romexis-common/` is the single source location for `RomexisPropertyAgent.java`, the Chilkat patch source and `dxservice_dummy.c`. These sources are compiled into the appropriate runtime images instead of being duplicated in final image directories.
`romexis-common/` is the single source location for `RomexisPropertyAgent.java`, `RomexisOptionPaneUIPatch.java`, the RxCr2 replacement and `dxservice_dummy.c`. The agent build embeds ASM and both targeted runtime patches into `RomexisPropertyAgent.jar`. These sources are compiled into the appropriate runtime images instead of being duplicated in final image directories.
### Server image build
+11 -2
@@ -148,7 +148,7 @@ ADMIN_JAVA_OPTS=-Xms256m -Xmx1024m
ADMIN_LANGUAGE=de
DEBUG_XTERM=false
ADMIN_VNC_LIFECYCLE=true
ENABLE_PROPERTY_AGENT=false
ENABLE_PROPERTY_AGENT=true
```
Wichtiges Verhalten:
@@ -217,4 +217,13 @@ Syntax:
PROPERTY_AGENT_SET_<RXPROPERTY_NAME>=<value>
```
Dies ist vor allem für die Romexis-Server-Runtime relevant. Im Admin-Container ist der PropertyAgent standardmäßig deaktiviert.
Der Server verwendet den Agenten für Runtime-Properties und den RxCr2-Ersatz.
Admin aktiviert ihn standardmäßig für die Service-INI-Integration und den
Java-17-`RomexisOptionPaneUI`-Null-Guard. Der Client lädt denselben Agenten aus
der GUI-Runtime, deaktiviert RxCr2 und aktiviert standardmäßig den
OptionPane-Patch.
```env
ROMEXIS_AGENT_RXCR2_PATCH=true
ROMEXIS_AGENT_OPTIONPANE_PATCH=true
```
+10 -2
@@ -148,7 +148,7 @@ ADMIN_JAVA_OPTS=-Xms256m -Xmx1024m
ADMIN_LANGUAGE=de
DEBUG_XTERM=false
ADMIN_VNC_LIFECYCLE=true
ENABLE_PROPERTY_AGENT=false
ENABLE_PROPERTY_AGENT=true
```
Important behavior:
@@ -217,4 +217,12 @@ Syntax:
PROPERTY_AGENT_SET_<RXPROPERTY_NAME>=<value>
```
This is primarily relevant for the Romexis server runtime. In the Admin container the PropertyAgent is disabled by default.
The server uses the agent for runtime properties and the RxCr2 replacement.
Admin enables the agent by default for its service-INI integration and the Java
17 `RomexisOptionPaneUI` null guard. The Client loads the same GUI-runtime agent,
disables RxCr2 and enables the OptionPane patch by default.
```env
ROMEXIS_AGENT_RXCR2_PATCH=true
ROMEXIS_AGENT_OPTIONPANE_PATCH=true
```
+1 -1
@@ -44,7 +44,7 @@ romexis-firebird-payload/
Builds a Firebird SQL payload from the official macOS installer.
romexis-common/
Contains shared PropertyAgent, Chilkat patch and DxService compatibility sources.
Enthält die gemeinsamen PropertyAgent-, RomexisOptionPaneUI-, RxCr2-Patch- und DxService-Kompatibilitätsquellen.
romexis-base/
Builds the reusable Java 11 server runtime image.
+1 -1
@@ -44,7 +44,7 @@ romexis-firebird-payload/
Builds a Firebird SQL payload from the official macOS installer.
romexis-common/
Contains shared PropertyAgent, Chilkat patch and DxService compatibility sources.
Contains the shared PropertyAgent, RomexisOptionPaneUI and RxCr2 patch sources, and DxService compatibility source.
romexis-base/
Builds the reusable Java 11 server runtime image.
+117 -10
@@ -4,11 +4,11 @@
## Zweck
Der `RomexisPropertyAgent` ist ein kleiner Java-Instrumentation-Agent, den das Romexis-Docker-Projekt verwendet, um Romexis-`RxProperties` während des JVM-Starts zu konfigurieren.
Der `RomexisPropertyAgent` ist ein Java-Instrumentation-Agent, den das Romexis-Docker-Projekt verwendet, um Romexis-`RxProperties` zu konfigurieren und eng begrenzte Runtime-Kompatibilitätspatches während des JVM-Starts anzuwenden.
Er ermöglicht es, ausgewählte Romexis-Runtime-Eigenschaften durch Umgebungsvariablen zu setzen, bevor die Romexis-Server-Anwendung vollständig startet.
Dies ist erforderlich, da bestimmtes Romexis-Verhalten sehr früh während des JVM-Starts festgelegt wird und später nicht zuverlässig durch Bearbeiten von Dateien im Container geändert werden kann.
Dies ist erforderlich, da bestimmtes Romexis-Verhalten sehr früh während des JVM-Starts festgelegt wird und ausgewählte Kompatibilitätskorrekturen vor dem Definieren der betroffenen Klassen angewendet werden müssen.
---
@@ -67,7 +67,7 @@ Der Java-Agent-Ansatz vermeidet:
- die Pflege benutzerdefinierter Binär-Patches
- das erneute Bauen von Romexis selbst
Stattdessen kann die Docker-Runtime diese Einstellungen mit gewöhnlichen Umgebungsvariablen steuern.
Stattdessen kann die Docker-Runtime diese Einstellungen und gezielte Transformationen beim Laden von Klassen mit gewöhnlichen Umgebungsvariablen steuern. Proprietäre Romexis-JAR-Dateien bleiben auf dem Datenträger unverändert.
Dies ist sicherer, einfacher zu pflegen und besser für automatisierte Deployments geeignet.
@@ -105,6 +105,81 @@ Danach sucht er das passende öffentliche Feld in `RxProperties`.
Existiert das Feld, liest der Agent den tatsächlichen Romexis-Property-Schlüssel und ruft die passende Methode `RxProperties.setProperty(...)` auf.
Der gleiche `premain`-Einstiegspunkt registriert außerdem Java-Instrumentation-
Transformer, bevor Romexis die betroffenen Klassen lädt. Jeder Transformer
gleicht genau einen Klassennamen ab und liefert die ursprünglichen Bytes
unverändert zurück, wenn der Patch deaktiviert, nicht anwendbar oder nicht sicher
ausführbar ist.
---
## Runtime-Kompatibilitätspatches
### RxCr2-Ersatz
Die Server-Runtime kann `romexis_lib_resource.RxCr2` durch die eingebettete
Java-Standard-PBKDF2-Implementierung ersetzen. Dadurch entfällt die
serverseitige Abhängigkeit vom ursprünglichen Chilkat-basierten Passwort-Hashing,
ohne `RomexisServer.jar` zu verändern.
```env
ROMEXIS_AGENT_RXCR2_PATCH=true
ROMEXIS_AGENT_RXCR2_SALT_MODE=base64
ROMEXIS_AGENT_RXCR2_DEBUG=false
```
Admin und Client deaktivieren diesen serverspezifischen Ersatz.
### RomexisOptionPaneUI-Null-Guard
Admin und Client laufen unter Java 17. Ein konkretes Swing-Lifecycle-Rennen
wurde in folgender Methode beobachtet:
```text
romexis_laf.RomexisOptionPaneUI$MyPCListener.propertyChange(...)
```
Unter neueren Java-Versionen, insbesondere Java 17, kann sich das Timing der
`PropertyChange`-Events im AWT-Event-Thread leicht unterscheiden. In diesem Fall
feuert das Event einen Sekundenbruchteil zu früh, bevor die Planmeca-Klasse ihre
UI-Komponente `m_MessageArea` initialisiert hat. Wenn Romexis anschließend die
bevorzugte Dialoggröße berechnet, führt der ursprüngliche Listener Folgendes aus:
```java
m_MessageArea.getPreferredSize()
```
auf einer `null`-Referenz. Die resultierende `NullPointerException` tritt im
AWT-Event-Thread auf und kann die gesamte Anwendung beenden, statt nur das
Pop-up zu zeichnen.
`RomexisOptionPaneUIPatch` verwendet die eingebettete ASM-Bibliothek und
transformiert ausschließlich die Methode
`propertyChange(PropertyChangeEvent)` des Listeners. Unmittelbar vor jedem
passenden `Container.getPreferredSize()`-Aufruf fügt er das Bytecode-Äquivalent
zu Folgendem ein:
```java
if (container == null) {
return;
}
```
Alle anderen ursprünglichen Klassenbytes und das proprietäre Romexis-JAR bleiben
unverändert. Enthält eine künftige Romexis-Version das erwartete Bytecode-Muster
nicht mehr, protokolliert der Transformer einen Fehler und liefert die
unveränderten Klassenbytes zurück, statt den Anwendungsstart zu verhindern.
Der Patch ist standardmäßig aktiv und kann in beiden Formen gesteuert werden:
```env
ROMEXIS_AGENT_OPTIONPANE_PATCH=true
```
```text
-Dromexis.agent.optionpane.patch=true
```
---
## Unterstützte Werttypen
@@ -142,13 +217,15 @@ Der Java Property Agent ist vorgesehen für:
- automatisiertes Konfigurationsmanagement
- Runtime-Anpassungen
- Korrekturen der Plattformkompatibilität
- kontrollierte Overrides des Romexis-Serververhaltens
- kontrollierte Overrides des Romexis-Runtime-Verhaltens
---
## Build-Integration
Der Quellcode des Agents wird beim Build des Romexis-Server-Images kompiliert.
Die kanonischen Quellen liegen unter `romexis-common/`. Der Agent wird sowohl in
die Java-11-Server-Runtime als auch in die von Admin und Client gemeinsam
verwendete Java-17-GUI-Runtime eingebaut.
Das Dockerfile verwendet eine dedizierte Build-Stage:
@@ -156,12 +233,18 @@ Das Dockerfile verwendet eine dedizierte Build-Stage:
agent-build
```
Das Ergebnis wird in das finale Image kopiert als:
Das erzeugte JAR liegt abhängig von der Runtime unter folgenden Pfaden:
```text
/opt/romexis/server/RomexisPropertyAgent.jar
/opt/romexis/admin/RomexisPropertyAgent.jar
/opt/romexis-runtime/RomexisPropertyAgent.jar
```
Das Agent-JAR enthält `RomexisOptionPaneUIPatch.class`, den eingebetteten
RxCr2-Ersatz und ASM selbst. Zur Laufzeit ist deshalb keine zusätzliche
Java-Abhängigkeit erforderlich.
Das JAR-Manifest enthält:
```text
@@ -178,7 +261,9 @@ Dadurch kann die JVM es laden über:
## Runtime-Integration
Der Romexis-Entrypoint fügt den Java-Agent dem JVM-Startbefehl von Romexis Server hinzu.
Server-Entrypoint, Admin-Launcher und Client-Launcher fügen den Java-Agenten ihrem
jeweiligen JVM-Startbefehl hinzu. Compose aktiviert ihn für Admin, und der Client
aktiviert ihn, wenn das JAR aus der gemeinsamen Runtime vorhanden ist.
Das Property-Override wird damit angewendet, bevor `RomexisServer.jar` seine normale Startsequenz fortsetzt.
@@ -188,6 +273,9 @@ Typische Runtime-Konfiguration:
PROPERTY_AGENT_SET_KEY_B_KEYVAULT_PWD_LOCATION_SERVER_PROPERTIES=true
```
Beim Client deaktiviert der Launcher den RxCr2-Ersatz explizit und aktiviert den
OptionPane-Patch. Auch Admin verwendet den OptionPane-Patch standardmäßig.
---
## Beispielhafte Log-Ausgabe
@@ -205,13 +293,21 @@ Unbekannte Eigenschaft:
JavaAgent WARN: RxProperties field not found: SOME_UNKNOWN_FIELD
```
Erfolgreiche Installation und Anwendung des Swing-Patches:
```text
JavaAgent: RomexisOptionPaneUI MyPCListener null-guard transformer installed
JavaAgent: RomexisOptionPaneUI MyPCListener patched successfully; inserted null guards=<count>
```
---
## Wichtige Hinweise
- Der Agent verändert keine Romexis-Binärdateien.
- Der Agent patcht keine Klassendateien.
- Der Agent ruft ausschließlich öffentliche `RxProperties`-Felder und Setter-Methoden auf.
- Der Agent verändert keine proprietären Romexis-JAR-Dateien auf dem Datenträger.
- Aktivierte Transformer können die In-Memory-Bytes ausdrücklich ausgewählter Klassen beim Laden verändern.
- Property-Overrides rufen öffentliche `RxProperties`-Felder und Setter-Methoden auf.
- Der OptionPane-Transformer ist auf eine Listener-Methode und ein fehlerhaftes Dereferenzierungsmuster begrenzt.
- Unbekannte Felder werden mit einer Warnung ignoriert.
- Dieser Mechanismus sollte nur für Eigenschaften verwendet werden, die verstanden und bewusst überschrieben werden.
@@ -222,3 +318,14 @@ JavaAgent WARN: RxProperties field not found: SOME_UNKNOWN_FIELD
| Eigenschaft | Wert | Grund |
|---|---|---|
| `KEY_B_KEYVAULT_PWD_LOCATION_SERVER_PROPERTIES` | `true` | Zwingt Romexis Server zu dem auf Server-Properties basierenden Verhalten, das für den Linux-Docker-Start erforderlich ist |
---
## Runtime-Patch-Steuerung
| Einstellung | Standard | Geltungsbereich |
|---|---|---|
| `ROMEXIS_AGENT_RXCR2_PATCH` | `true` | Serverseitiger RxCr2-Ersatz; von Admin und Client explizit deaktiviert |
| `ROMEXIS_AGENT_RXCR2_SALT_MODE` | `base64` | Salt-Interpretation der RxCr2-PBKDF2-Implementierung |
| `ROMEXIS_AGENT_RXCR2_DEBUG` | `false` | Zusätzliche nicht geheime RxCr2-Diagnoseausgaben |
| `ROMEXIS_AGENT_OPTIONPANE_PATCH` | `true` | Java-17-Swing-Lifecycle-Null-Guard für Admin und Client |
+114 -10
@@ -4,11 +4,11 @@
## Purpose
The `RomexisPropertyAgent` is a small Java Instrumentation Agent used by the Romexis Docker project to configure Romexis `RxProperties` during JVM startup.
The `RomexisPropertyAgent` is a Java Instrumentation Agent used by the Romexis Docker project to configure Romexis `RxProperties` and apply narrowly scoped runtime compatibility patches during JVM startup.
It allows selected Romexis runtime properties to be set through environment variables before the Romexis Server application fully starts.
This is required because some Romexis behavior is decided very early during JVM startup and cannot reliably be changed later by editing files inside the container.
This is required because some Romexis behavior is decided very early during JVM startup and because selected compatibility fixes must be applied before the affected classes are defined.
---
@@ -67,7 +67,7 @@ The Java agent approach avoids:
- maintaining custom binary patches
- rebuilding Romexis itself
Instead, the Docker runtime can control these settings using ordinary environment variables.
Instead, the Docker runtime can control these settings and targeted class-load-time transformations using ordinary environment variables. Proprietary Romexis JAR files remain unchanged on disk.
This is safer, easier to maintain and better suited for automated deployments.
@@ -105,6 +105,78 @@ Then it looks up the matching public field in `RxProperties`.
If the field exists, the agent reads the actual Romexis property key and calls the matching `RxProperties.setProperty(...)` method.
The same `premain` entry point also registers Java instrumentation transformers
before Romexis loads the affected classes. Each transformer matches one exact
class name and returns the original bytes unchanged when the patch is disabled,
not applicable or cannot be applied safely.
---
## Runtime Compatibility Patches
### RxCr2 Replacement
The server runtime can replace `romexis_lib_resource.RxCr2` with the embedded
Java-standard PBKDF2 implementation. This removes the server-side dependency on
the original Chilkat-based password hashing path without modifying
`RomexisServer.jar`.
```env
ROMEXIS_AGENT_RXCR2_PATCH=true
ROMEXIS_AGENT_RXCR2_SALT_MODE=base64
ROMEXIS_AGENT_RXCR2_DEBUG=false
```
Admin and Client disable this server-specific replacement.
### RomexisOptionPaneUI Null Guard
Admin and Client run on Java 17. A concrete Swing lifecycle race was observed in:
```text
romexis_laf.RomexisOptionPaneUI$MyPCListener.propertyChange(...)
```
On newer Java versions, especially Java 17, the timing of `PropertyChange`
events on the AWT event thread can differ slightly. In this case the event can
fire a fraction too early, before the Planmeca class has initialized its
`m_MessageArea` UI component. When Romexis then calculates the preferred dialog
size, the original listener executes:
```java
m_MessageArea.getPreferredSize()
```
against a `null` reference. The resulting `NullPointerException` occurs on the
AWT event thread and can terminate the complete application instead of merely
drawing the popup.
`RomexisOptionPaneUIPatch` uses the bundled ASM library to transform only the
listener's `propertyChange(PropertyChangeEvent)` method. Immediately before each
matching `Container.getPreferredSize()` invocation, it inserts the bytecode
equivalent of:
```java
if (container == null) {
return;
}
```
All other original class bytes and the proprietary Romexis JAR are preserved.
If a future Romexis version no longer contains the expected bytecode pattern,
the transformer logs an error and returns the unmodified class bytes instead of
making application startup fail.
The patch is enabled by default and can be controlled with either form:
```env
ROMEXIS_AGENT_OPTIONPANE_PATCH=true
```
```text
-Dromexis.agent.optionpane.patch=true
```
---
## Supported Value Types
@@ -142,13 +214,15 @@ The Java Property Agent is intended for:
- automated configuration management
- runtime customization
- platform compatibility fixes
- controlled Romexis server behavior overrides
- controlled Romexis runtime behavior overrides
---
## Build Integration
The agent source is compiled during the Romexis Server image build.
The canonical sources live in `romexis-common/`. The agent is built into both
the Java 11 server runtime and the shared Java 17 GUI runtime used by Admin and
Client.
The Dockerfile uses a dedicated build stage:
@@ -156,12 +230,18 @@ The Dockerfile uses a dedicated build stage:
agent-build
```
The result is copied into the final image as:
The resulting JAR is available at these runtime-specific paths:
```text
/opt/romexis/server/RomexisPropertyAgent.jar
/opt/romexis/admin/RomexisPropertyAgent.jar
/opt/romexis-runtime/RomexisPropertyAgent.jar
```
The agent JAR contains `RomexisOptionPaneUIPatch.class`, the embedded RxCr2
replacement and ASM itself, so no external Java dependency is required at
runtime.
The JAR manifest contains:
```text
@@ -178,7 +258,9 @@ This allows the JVM to load it through:
## Runtime Integration
The Romexis entrypoint adds the Java agent to the Romexis Server JVM startup command.
The Server entrypoint, Admin launcher and Client launcher add the Java agent to
their respective JVM startup commands. Compose enables it for Admin, and the
Client enables it when the shared runtime JAR is present.
The property override is then applied before `RomexisServer.jar` continues its normal startup sequence.
@@ -188,6 +270,9 @@ Typical runtime configuration:
PROPERTY_AGENT_SET_KEY_B_KEYVAULT_PWD_LOCATION_SERVER_PROPERTIES=true
```
For the Client, the launcher explicitly disables the RxCr2 replacement and
enables the OptionPane patch. Admin also uses the OptionPane patch by default.
---
## Example Log Output
@@ -205,13 +290,21 @@ Unknown property:
JavaAgent WARN: RxProperties field not found: SOME_UNKNOWN_FIELD
```
Successful Swing patch installation and application:
```text
JavaAgent: RomexisOptionPaneUI MyPCListener null-guard transformer installed
JavaAgent: RomexisOptionPaneUI MyPCListener patched successfully; inserted null guards=<count>
```
---
## Important Notes
- The agent does not modify Romexis binaries.
- The agent does not patch class files.
- The agent only calls public `RxProperties` fields and setter methods.
- The agent does not modify proprietary Romexis JAR files on disk.
- Enabled transformers can modify the in-memory bytes of explicitly targeted classes while they are loaded.
- Property overrides call public `RxProperties` fields and setter methods.
- The OptionPane transformer is limited to one listener method and one failing dereference pattern.
- Unknown fields are ignored with a warning.
- This mechanism should only be used for properties that are understood and intentionally overridden.
@@ -223,4 +316,15 @@ JavaAgent WARN: RxProperties field not found: SOME_UNKNOWN_FIELD
|---|---|---|
| `KEY_B_KEYVAULT_PWD_LOCATION_SERVER_PROPERTIES` | `true` | Forces Romexis Server to use the server-properties based behavior required for Linux Docker startup |
---
## Runtime Patch Controls
| Setting | Default | Scope |
|---|---|---|
| `ROMEXIS_AGENT_RXCR2_PATCH` | `true` | Server-side RxCr2 replacement; explicitly disabled by Admin and Client |
| `ROMEXIS_AGENT_RXCR2_SALT_MODE` | `base64` | Salt interpretation for the RxCr2 PBKDF2 implementation |
| `ROMEXIS_AGENT_RXCR2_DEBUG` | `false` | Additional non-secret RxCr2 diagnostics |
| `ROMEXIS_AGENT_OPTIONPANE_PATCH` | `true` | Java 17 Swing lifecycle null guard for Admin and Client |
+1
@@ -26,6 +26,7 @@
│ └── ci-publish-manifests.sh
├── romexis-common/
│ ├── RomexisPropertyAgent.java
│ ├── RomexisOptionPaneUIPatch.java
│ ├── dxservice_dummy.c
│ └── patches-src/
├── romexis-base/
+1
@@ -26,6 +26,7 @@
│ └── ci-publish-manifests.sh
├── romexis-common/
│ ├── RomexisPropertyAgent.java
│ ├── RomexisOptionPaneUIPatch.java
│ ├── dxservice_dummy.c
│ └── patches-src/
├── romexis-base/
+6 -2
@@ -265,7 +265,7 @@ ADMIN_JAVA_OPTS=-Xms256m -Xmx1024m
ADMIN_LANGUAGE=de
DEBUG_XTERM=false
ADMIN_VNC_LIFECYCLE=true
ENABLE_PROPERTY_AGENT=false
ENABLE_PROPERTY_AGENT=true
```
`ADMIN_LANGUAGE` unterstützt:
@@ -544,7 +544,11 @@ Beispiel:
PROPERTY_AGENT_SET_KEY_B_KEYVAULT_PWD_LOCATION_SERVER_PROPERTIES=true
```
Dies ist hauptsächlich für die Romexis-Server-Laufzeit relevant. Im Admin-Container ist der PropertyAgent standardmäßig deaktiviert.
Der Server verwendet den Agenten hauptsächlich für Runtime-Properties. Admin
aktiviert ihn standardmäßig, und Admin sowie Client verwenden seinen
Java-17-`RomexisOptionPaneUI`-Null-Guard gegen die Swing-Lifecycle-
`NullPointerException`, die durch ein frühes `PropertyChange`-Event vor der
Initialisierung von `m_MessageArea` entsteht.
---
+5 -2
@@ -267,7 +267,7 @@ ADMIN_JAVA_OPTS=-Xms256m -Xmx1024m
ADMIN_LANGUAGE=en
DEBUG_XTERM=false
ADMIN_VNC_LIFECYCLE=true
ENABLE_PROPERTY_AGENT=false
ENABLE_PROPERTY_AGENT=true
```
`ADMIN_LANGUAGE` supports:
@@ -546,7 +546,10 @@ Example:
PROPERTY_AGENT_SET_KEY_B_KEYVAULT_PWD_LOCATION_SERVER_PROPERTIES=true
```
This is primarily relevant for the Romexis server runtime. In the Admin container the PropertyAgent is disabled by default.
The server uses the agent primarily for runtime properties. Admin enables the
agent by default, and Admin and Client use its Java 17 `RomexisOptionPaneUI`
null guard to prevent the Swing lifecycle `NullPointerException` caused by an
early `PropertyChange` event before `m_MessageArea` is initialized.
---
+16 -4
@@ -123,20 +123,32 @@ ADMIN_JAVA_OPTS=-Xms256m -Xmx1024m
ADMIN_LANGUAGE=de
DEBUG_XTERM=false
ADMIN_VNC_LIFECYCLE=true
ENABLE_PROPERTY_AGENT=false
ENABLE_PROPERTY_AGENT=true
```
---
## PropertyAgent im Admin
Der Romexis PropertyAgent ist für den Admin-Container standardmäßig deaktiviert:
Der Romexis PropertyAgent ist für den Admin-Container standardmäßig aktiviert:
```env
ENABLE_PROPERTY_AGENT=false
ENABLE_PROPERTY_AGENT=true
```
Grund: `RxProperties` ist während der Java-Agent-Phase `premain` beim Start von RomexisConfig nicht immer sichtbar. Der Server-Container verwendet den PropertyAgent weiterhin für die serverseitige Injektion von Laufzeiteigenschaften.
Der Agent setzt den Linux-spezifischen Admin-Service-INI-Pfad und stellt den für
den zuverlässigen Betrieb unter Java 17 erforderlichen `RomexisOptionPaneUI`-
Null-Guard bereit. Der Guard verhindert eine Swing-Lifecycle-
`NullPointerException`, wenn ein `PropertyChange`-Event den Planmeca-Listener
erreicht, bevor `m_MessageArea` initialisiert wurde. Der serverspezifische
RxCr2-Ersatz bleibt in Admin über `ROMEXIS_AGENT_RXCR2_PATCH=false` deaktiviert.
Der Patch ist im Agenten standardmäßig aktiv. Nur für einen kontrollierten
Vergleich kann er folgendermaßen deaktiviert werden:
```env
ROMEXIS_AGENT_OPTIONPANE_PATCH=false
```
---
+16 -4
@@ -123,20 +123,32 @@ ADMIN_JAVA_OPTS=-Xms256m -Xmx1024m
ADMIN_LANGUAGE=de
DEBUG_XTERM=false
ADMIN_VNC_LIFECYCLE=true
ENABLE_PROPERTY_AGENT=false
ENABLE_PROPERTY_AGENT=true
```
---
## PropertyAgent in Admin
The Romexis PropertyAgent is disabled by default for the Admin container:
The Romexis PropertyAgent is enabled by default for the Admin container:
```env
ENABLE_PROPERTY_AGENT=false
ENABLE_PROPERTY_AGENT=true
```
Reason: `RxProperties` is not always visible during the Java agent `premain` phase when RomexisConfig is started. The server container still uses the PropertyAgent for server-side runtime property injection.
The agent sets the Linux-specific Admin service INI path and supplies the
`RomexisOptionPaneUI` null guard required for reliable operation on Java 17.
The guard prevents a Swing lifecycle `NullPointerException` when a
`PropertyChange` event reaches the Planmeca listener before `m_MessageArea` has
been initialized. The server-specific RxCr2 replacement remains disabled in
Admin through `ROMEXIS_AGENT_RXCR2_PATCH=false`.
The patch is enabled by default inside the agent. It can be disabled only for a
controlled comparison with:
```env
ROMEXIS_AGENT_OPTIONPANE_PATCH=false
```
---
+111
@@ -74,3 +74,114 @@ romexis-client:latest
```
Zuerst werden die Architektur-Tags erstellt. Die öffentlichen Multi-Architektur-Tags werden erst veröffentlicht, wenn beide Architekturen erfolgreich abgeschlossen wurden.
---
## Laufzeitverhalten
Der Container startet Xvfb, Openbox, idesk, x11vnc und noVNC. Romexis selbst
startet nicht automatisch. Öffne den noVNC-Desktop und doppelklicke auf das
Symbol **Romexis Client**. Dadurch belegt eine ungenutzte Client-Sitzung keinen
großen Java-Heap, und der Anwendungsstart bleibt für den Bediener sichtbar.
Der Launcher verhindert über eine Sperrdatei doppelte Romexis-Prozesse und
schreibt das Client-Protokoll nach:
```text
/tmp/romexis-client.log
```
Das optionale Debug-Terminal wird über `CLIENT_DEBUG_XTERM` gesteuert.
---
## Browser- und Runtime-Konfiguration
Die Standardadresse im Browser lautet:
```text
http://localhost:6081/vnc.html?autoconnect=true
```
| Variable | Standard | Zweck |
|---|---|---|
| `CLIENT_NOVNC_PORT` | `6081` | Veröffentlichter noVNC-Hostport |
| `CLIENT_VNC_PASSWORD` | `promax` | Passwort des internen VNC-Servers |
| `CLIENT_RESOLUTION` | `1280x900x24` | Auflösung des virtuellen Desktops |
| `CLIENT_JAVA_OPTS` | `-Xss500k -Xmx16G` | JVM-Optionen des Clients |
| `CLIENT_LANGUAGE` | `de` | Romexis-Sprache |
| `CLIENT_COUNTRY` | `DE` | Land der Java-Locale |
| `CLIENT_DEBUG_XTERM` | `false` | Aktiviert ein zusätzliches Debug-Terminal |
| `ROMEXIS_AGENT_OPTIONPANE_PATCH` | `true` | Aktiviert die Java-17-Swing-Lifecycle-Korrektur |
Compose veröffentlicht nur noVNC. x11vnc lauscht innerhalb des Containers auf
Port `5900`, wird standardmäßig aber nicht als Hostport veröffentlicht.
---
## RMI-Auflösung und Identität
Der Client verwendet den öffentlichen `SERVER_RMI_HOSTNAME` als Server- und
Zertifikatsidentität. Beim Containerstart wird dieser Hostname auf die interne
Adresse des Compose-Dienstes `romexis` abgebildet. Der Client-Launcher verbindet
sich auch bei übersetzten öffentlichen Hostports mit den festen Containerports
`1099` und `2099`.
Bei einer Portübersetzung sollte ein DNS-Name statt einer IP-Adresse verwendet
werden. Eine IP-Adresse kann nicht über `/etc/hosts` auf den internen Dienst
umgebogen werden.
---
## RomexisOptionPaneUI-Patch
Beim Start des Clients wird der gemeinsame `RomexisPropertyAgent` geladen. Sein
serverspezifischer RxCr2-Ersatz ist deaktiviert, der OptionPane-Patch dagegen
standardmäßig aktiv.
Unter Java 17 kann ein AWT-Property-Change-Event einen Sekundenbruchteil zu früh
ausgeführt werden, bevor die Planmeca-Klasse `m_MessageArea` initialisiert hat.
Wenn der ursprüngliche Listener danach die Dialoggröße berechnet, ruft er
`getPreferredSize()` auf dieser `null`-Referenz auf. Die resultierende
`NullPointerException` tritt im AWT-Event-Thread auf und kann die gesamte
Anwendung beenden, statt nur das Pop-up zu zeichnen.
`RomexisOptionPaneUIPatch` transformiert ausschließlich
`romexis_laf.RomexisOptionPaneUI$MyPCListener.propertyChange()` und ergänzt
unmittelbar vor dem fehlerhaften Aufruf einen Null-Guard. Das ursprüngliche
Romexis-JAR bleibt auf dem Datenträger unverändert. Der Patch sollte nur für
einen kontrollierten Vergleich deaktiviert werden:
```env
ROMEXIS_AGENT_OPTIONPANE_PATCH=false
```
---
## Persistente Daten und Healthcheck
Die Client-ProgramData liegen getrennt vom Server- und Admin-Zustand:
```text
${ROMEXIS_DATA_ROOT}/docker/client/programdata
-> /ProgramData/Planmeca/Romexis
```
Der Healthcheck prüft X-Display, laufenden `Romexis.jar`-Prozess und noVNC-Port.
Da Romexis bedarfsgesteuert startet, kann der Dienst bis zum Doppelklick auf das
Desktop-Symbol im Zustand `starting` bleiben oder `unhealthy` werden.
---
## Betrieb und Fehleranalyse
```bash
docker compose up -d romexis-client
docker compose logs -f romexis-client
docker compose exec romexis-client tail -f /tmp/romexis-client.log
```
Wenn kein Desktop erscheint, prüfe die Meldungen von Xvfb, Openbox, x11vnc und
websockify im Containerprotokoll. Beendet sich Romexis nach dem Aktivieren des
Symbols, prüfe `/tmp/romexis-client.log` und stelle sicher, dass
`SERVER_RMI_HOSTNAME` auf den internen Dienst `romexis` aufgelöst wird.
+109
@@ -74,3 +74,112 @@ romexis-client:latest
```
The architecture tags are created first. The public multi-architecture tags are published only after both architectures completed successfully.
---
## Runtime Behavior
The container starts Xvfb, Openbox, idesk, x11vnc and noVNC. Romexis itself is
not started automatically. Open the noVNC desktop and double-click the
**Romexis Client** icon. This keeps an unused Client session from consuming a
large Java heap and makes application startup visible to the operator.
The launcher uses a lock file to prevent duplicate Romexis processes and writes
the Client log to:
```text
/tmp/romexis-client.log
```
The optional debug terminal is controlled by `CLIENT_DEBUG_XTERM`.
---
## Browser and Runtime Configuration
The default browser URL is:
```text
http://localhost:6081/vnc.html?autoconnect=true
```
| Variable | Default | Purpose |
|---|---|---|
| `CLIENT_NOVNC_PORT` | `6081` | Published noVNC host port |
| `CLIENT_VNC_PASSWORD` | `promax` | Password for the internal VNC server |
| `CLIENT_RESOLUTION` | `1280x900x24` | Virtual desktop resolution |
| `CLIENT_JAVA_OPTS` | `-Xss500k -Xmx16G` | Client JVM options |
| `CLIENT_LANGUAGE` | `de` | Romexis language |
| `CLIENT_COUNTRY` | `DE` | Java locale country |
| `CLIENT_DEBUG_XTERM` | `false` | Enables an additional debug terminal |
| `ROMEXIS_AGENT_OPTIONPANE_PATCH` | `true` | Enables the Java 17 Swing lifecycle fix |
Compose publishes noVNC only. x11vnc listens on port `5900` inside the
container but is not exposed as a host port by default.
---
## RMI Resolution and Identity
The Client uses the public `SERVER_RMI_HOSTNAME` as the server and certificate
identity. During container startup, that hostname is mapped to the internal
address of the Compose service `romexis`. The Client launcher connects to the
fixed container ports `1099` and `2099`, even when the corresponding public host
ports are translated.
Use a DNS hostname rather than an IP address when port translation is required.
An IP address cannot be remapped to the internal service through `/etc/hosts`.
---
## RomexisOptionPaneUI Patch
The shared `RomexisPropertyAgent` is loaded when the Client starts. Its
server-specific RxCr2 replacement is disabled, while the OptionPane patch is
enabled by default.
Under Java 17, an AWT property-change event can run a fraction too early,
before the Planmeca class has initialized `m_MessageArea`. When the original
listener subsequently calculates the dialog size, it calls
`getPreferredSize()` on this `null` reference. The resulting
`NullPointerException` occurs on the AWT event thread and can terminate the
complete application instead of merely drawing the popup.
`RomexisOptionPaneUIPatch` transforms only
`romexis_laf.RomexisOptionPaneUI$MyPCListener.propertyChange()` and inserts a
null guard immediately before the failing call. The original Romexis JAR stays
unchanged on disk. Disable the patch only for a controlled comparison:
```env
ROMEXIS_AGENT_OPTIONPANE_PATCH=false
```
---
## Persistent Data and Healthcheck
Client ProgramData is stored separately from Server and Admin state:
```text
${ROMEXIS_DATA_ROOT}/docker/client/programdata
-> /ProgramData/Planmeca/Romexis
```
The healthcheck validates the X display, the running `Romexis.jar` process and
the noVNC port. Because Romexis starts on demand, the service can remain in
`starting` or become `unhealthy` until the desktop icon has been used.
---
## Operations and Troubleshooting
```bash
docker compose up -d romexis-client
docker compose logs -f romexis-client
docker compose exec romexis-client tail -f /tmp/romexis-client.log
```
If no desktop appears, check the Xvfb, Openbox, x11vnc and websockify messages in
the container log. If Romexis exits after the icon is activated, inspect
`/tmp/romexis-client.log` and confirm that `SERVER_RMI_HOSTNAME` resolves to the
internal `romexis` service.