Table of Contents
- Java Property Agent
- Purpose
- Why the Agent Exists
- Required Docker Setting
- Why a Java Agent Instead of Patching Files?
- How It Works
- Runtime Compatibility Patches
- Supported Value Types
- Unknown Properties
- Intended Use Cases
- Build Integration
- Runtime Integration
- Example Log Output
- Important Notes
- Current Critical Property
- Runtime Patch Controls
Deutsch | English
Java Property Agent
Purpose
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 because selected compatibility fixes must be applied before the affected classes are defined.
Why the Agent Exists
When starting RomexisServer.jar under Linux, Romexis internally selected behavior that matched the macOS runtime path.
That macOS-specific behavior was not compatible with the Linux Docker environment.
The critical property was:
KEY_B_KEYVAULT_PWD_LOCATION_SERVER_PROPERTIES
For the Romexis Server to start correctly inside the Linux container, this property had to be set to:
true
This makes Romexis behave like the Windows server runtime in this area and use the expected server properties based key vault password location.
Without this override, the Romexis Server startup under Linux could fail because the wrong platform-specific property handling was selected.
Required Docker Setting
The most important environment variable currently used by the Docker image is:
PROPERTY_AGENT_SET_KEY_B_KEYVAULT_PWD_LOCATION_SERVER_PROPERTIES=true
This is translated by the Java agent into:
RxProperties.setProperty(
RxProperties.KEY_B_KEYVAULT_PWD_LOCATION_SERVER_PROPERTIES,
true
);
This override is one of the reasons why Romexis Server can run reliably in the Linux-based container.
Why a Java Agent Instead of Patching Files?
The Java agent approach avoids:
- patching Romexis application files
- modifying proprietary Romexis JARs
- editing configuration files after startup has already begun
- maintaining custom binary patches
- rebuilding Romexis itself
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.
How It Works
The agent is loaded by the JVM before the Romexis application starts.
It scans all environment variables with the prefix:
PROPERTY_AGENT_SET_
The part after the prefix is interpreted as a field name from:
romexis_lib_base.types.RxProperties
Example:
PROPERTY_AGENT_SET_KEY_B_KEYVAULT_PWD_LOCATION_SERVER_PROPERTIES=true
The agent removes the prefix:
KEY_B_KEYVAULT_PWD_LOCATION_SERVER_PROPERTIES
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.
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:
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:
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:
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:
ROMEXIS_AGENT_OPTIONPANE_PATCH=true
-Dromexis.agent.optionpane.patch=true
Supported Value Types
The agent automatically converts values to one of the following types:
| Environment value | Java type |
|---|---|
true / false |
Boolean |
| integer values | Integer |
| all other values | String |
Unknown Properties
If an environment variable references a field that does not exist in RxProperties, the agent does not fail the startup.
Instead, it logs a warning:
JavaAgent WARN: RxProperties field not found: <field>
This makes the mechanism safe for optional or version-dependent properties.
Intended Use Cases
The Java Property Agent is intended for:
- Docker deployments
- Kubernetes deployments
- automated configuration management
- runtime customization
- platform compatibility fixes
- controlled Romexis runtime behavior overrides
Build Integration
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:
agent-build
The resulting JAR is available at these runtime-specific paths:
/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:
Premain-Class: RomexisPropertyAgent
This allows the JVM to load it through:
-javaagent:/opt/romexis/server/RomexisPropertyAgent.jar
Runtime Integration
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.
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
Successful property application:
JavaAgent: set KEY_B_KEYVAULT_PWD_LOCATION_SERVER_PROPERTIES=true
JavaAgent: 1 properties applied
Unknown property:
JavaAgent WARN: RxProperties field not found: SOME_UNKNOWN_FIELD
Successful Swing patch installation and application:
JavaAgent: RomexisOptionPaneUI MyPCListener null-guard transformer installed
JavaAgent: RomexisOptionPaneUI MyPCListener patched successfully; inserted null guards=<count>
Important Notes
- 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
RxPropertiesfields 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.
Current Critical Property
| Property | Value | Reason |
|---|---|---|
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 |
Romexis Docker Wiki
English
Getting Started
- Project Overview
- Architecture
- Quick Start
- Synology Quick Start
- Use with Docker + WSL in Windows
- Compose Runtime
- Configuration
- Container Images
Runtime Services
- Romexis Admin
- Romexis Client
- mRomexis Web App
- Runtime Layout
- Backup and Restore
- Troubleshooting
- Security
Build System
Database
Migration
Development
Source Documents
Deutsch
Erste Schritte
- Projektübersicht
- Architektur
- Schnellstart
- Synology Quick Start
- Nutzung mit Docker + WSL unter Windows
- Compose-Runtime
- Konfiguration
- Container-Images
Runtime-Dienste
- Romexis Admin
- Romexis Client
- mRomexis Web App
- Runtime-Layout
- Sicherung und Wiederherstellung
- Fehlerbehebung
- Sicherheit
Build-System
Datenbank
Migration
Entwicklung
Quelldokumente
Romexis Docker Project Wiki / Romexis-Docker-Projekt-Wiki
English Home · Deutsche Startseite · English source documents · Deutsche Quelldokumente · Security · Sicherheit
Internal operations and development wiki / Internes Betriebs- und Entwicklungswiki