[ 
https://issues.apache.org/jira/browse/UNOMI-917?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Serge Huber updated UNOMI-917:
------------------------------
    Attachment: verify_config_conflicts.py

> Dynamic configuration changes are overridden by custom.system.properties 
> because of Karaf's property override system.
> ---------------------------------------------------------------------------------------------------------------------
>
>                 Key: UNOMI-917
>                 URL: https://issues.apache.org/jira/browse/UNOMI-917
>             Project: Apache Unomi
>          Issue Type: Bug
>          Components: unomi(-core)
>    Affects Versions: unomi-3.0.0, unomi-2.7.0, unomi-3.1.0
>            Reporter: Serge Huber
>            Priority: Major
>             Fix For: unomi-3.2.0, unomi-4.0.0
>
>         Attachments: verify_config_conflicts.py
>
>
> h1. Configuration Admin Updates Not Applied Due to Karaf System Property 
> Override
> h2. Summary
> Configuration changes made via Karaf's {{config:property-set}} and 
> {{config:update}} commands are not being applied because Karaf's 
> {{KarafConfigurationPlugin}} automatically overrides Configuration Admin 
> properties when matching system properties or environment variables exist.
> h2. Problem Description
> h3. What's Happening
> When administrators try to update configuration properties using Karaf's 
> Configuration Admin commands:
> {code:java}
> config:edit org.apache.unomi.router
> config:property-set kafka.host my-kafka-server
> config:update
> {code}
> The changes are saved to the configuration file, but the actual component 
> doesn't receive the updated values. Instead, it continues using the values 
> from system properties or environment variables.
> h3. Root Cause
> Apache Karaf includes a {{KarafConfigurationPlugin}} that automatically 
> overrides Configuration Admin properties when it finds matching system 
> properties or environment variables. The override pattern is:
> *System Property Pattern:* {{configurationPid.propertyName}}
> For example:
>  * Configuration PID: {{org.apache.unomi.router}}
>  * Property name: {{kafka.host}}
>  * Karaf looks for: {{org.apache.unomi.router.kafka.host}}
> If this system property exists (either as a system property or environment 
> variable), Karaf *always* uses it, completely ignoring any Configuration 
> Admin updates.
> h3. Why This Is a Problem
> Unomi uses a large {{custom.system.properties}} file that contains many 
> properties following this exact naming convention. These properties were 
> originally created to allow environment variable overrides, but they now 
> prevent Configuration Admin from working properly.
> *Example:*
>  * {{.cfg}} file has: {{{}kafka.host = 
> $\{org.apache.unomi.router.kafka.host:-localhost{}}}}
>  * {{custom.system.properties}} has: 
> {{{}org.apache.unomi.router.kafka.host=$\{env:UNOMI_ROUTER_KAFKA_HOST:-localhost{}}}}
>  * Karaf sees the system property {{org.apache.unomi.router.kafka.host}} and 
> *always* overrides the Configuration Admin value
>  * Result: {{config:property-set}} changes are ignored
> h2. Affected Components
> The following configuration components are affected (excluding 
> {{org.apache.unomi.rest.authentication}} which is being fixed separately):
> h3. 1. {{org.apache.unomi.migration}} (1 property)
>  * *Property:* {{recoverFromHistory}}
>  * *System Property:* {{org.apache.unomi.migration.recoverFromHistory}}
> h3. 2. {{org.apache.unomi.router}} (13 properties)
>  * *Properties:* {{{}kafka.host{}}}, {{{}kafka.port{}}}, 
> {{{}kafka.import.topic{}}}, {{{}kafka.export.topic{}}}, 
> {{{}kafka.import.groupId{}}}, {{{}kafka.export.groupId{}}}, 
> {{{}kafka.consumerCount{}}}, {{{}kafka.autoCommit{}}}, 
> {{{}import.oneshot.uploadDir{}}}, {{{}executionsHistory.size{}}}, 
> {{{}executions.error.report.size{}}}, {{{}config.allowedEndpoints{}}}, 
> {{configs.refresh.interval}}
>  * *System Properties:* {{org.apache.unomi.router.*}} (all matching the 
> property names)
> h3. 3. {{org.apache.unomi.cluster}} (2 properties)
>  * *Properties:* {{{}nodeId{}}}, {{nodeStatisticsUpdateFrequency}}
>  * *System Properties:* {{{}org.apache.unomi.cluster.nodeId{}}}, 
> {{org.apache.unomi.cluster.nodeStatisticsUpdateFrequency}}
> h3. 4. {{org.apache.unomi.plugins.base}} (1 property)
>  * *Property:* {{maxProfilesInOneMerge}}
>  * *System Property:* {{org.apache.unomi.plugins.base.maxProfilesInOneMerge}}
> h3. 5. {{org.apache.unomi.services}} (1 property)
>  * *Property:* {{segment.max.retries.update.profile.segment}}
>  * *System Property:* 
> {{org.apache.unomi.services.segment.max.retries.update.profile.segment}}
> *Total:* 18 properties across 5 components
> h2. Proposed Solution
> h3. Strategy: Rename Properties in {{.cfg}} Files
> Rename the property names in {{.cfg}} files to use domain-specific prefixes 
> or hierarchical naming. This breaks the Karaf override pattern while 
> maintaining backward compatibility for variable substitution.
> h3. How It Works
> *Karaf Override Pattern:* {{PID.propertyName}} (exact match required)
> *Example for Router:*
>  * *Old:* {{.cfg}} has {{{}kafka.host{}}}, system property is 
> {{org.apache.unomi.router.kafka.host}} -> *MATCH* -> Override occurs
>  * *New:* {{.cfg}} has {{{}router.kafka.host{}}}, system property is 
> {{org.apache.unomi.router.kafka.host}} -> Karaf looks for 
> {{org.apache.unomi.router.router.kafka.host}} -> *NO MATCH* -> No override
> *Key Point:* The {{{}$\{...{}}}} system property references in {{.cfg}} files 
> remain unchanged. They still work for variable substitution, but they no 
> longer trigger Karaf's override mechanism.
> h3. Proposed Property Renames
> ||Component||Current Property||Proposed New Name||Rationale||
> |Migration|{{recoverFromHistory}}|{{migration.recoverFromHistory}}|Domain-specific
>  prefix|
> |Router|{{kafka.host}}|{{router.kafka.host}}|Add {{router.}} prefix to all 
> router properties|
> |Router|{{kafka.port}}|{{router.kafka.port}}|Add {{router.}} prefix to all 
> router properties|
> |Router|{{kafka.import.topic}}|{{router.kafka.import.topic}}|Add {{router.}} 
> prefix to all router properties|
> |Router|{{kafka.export.topic}}|{{router.kafka.export.topic}}|Add {{router.}} 
> prefix to all router properties|
> |Router|{{kafka.import.groupId}}|{{router.kafka.import.groupId}}|Add 
> {{router.}} prefix to all router properties|
> |Router|{{kafka.export.groupId}}|{{router.kafka.export.groupId}}|Add 
> {{router.}} prefix to all router properties|
> |Router|{{kafka.consumerCount}}|{{router.kafka.consumerCount}}|Add 
> {{router.}} prefix to all router properties|
> |Router|{{kafka.autoCommit}}|{{router.kafka.autoCommit}}|Add {{router.}} 
> prefix to all router properties|
> |Router|{{import.oneshot.uploadDir}}|{{router.import.oneshot.uploadDir}}|Add 
> {{router.}} prefix to all router properties|
> |Router|{{executionsHistory.size}}|{{router.executionsHistory.size}}|Add 
> {{router.}} prefix to all router properties|
> |Router|{{executions.error.report.size}}|{{router.executions.error.report.size}}|Add
>  {{router.}} prefix to all router properties|
> |Router|{{config.allowedEndpoints}}|{{router.config.allowedEndpoints}}|Add 
> {{router.}} prefix to all router properties|
> |Router|{{configs.refresh.interval}}|{{router.configs.refresh.interval}}|Add 
> {{router.}} prefix to all router properties|
> |Cluster|{{nodeId}}|{{cluster.nodeId}}|Domain-specific prefix|
> |Cluster|{{nodeStatisticsUpdateFrequency}}|{{cluster.nodeStatisticsUpdateFrequency}}|Domain-specific
>  prefix|
> |Plugins 
> Base|{{maxProfilesInOneMerge}}|{{merge.maxProfilesInOneMerge}}|Domain-specific
>  prefix|
> |Services|{{segment.max.retries.update.profile.segment}}|{{updateProfileSegment.maxRetries}}|More
>  readable, domain-specific|
> h3. Implementation Details
> * Update {{.cfg}} files:*
>  # Rename property names (left side of {{{}={}}})
>  # Keep {{{}$\{...{}}}} system property references unchanged (right side of 
> {{{}={}}})
>  # Add explanatory comments about why the naming is used
> *Update code references:*
>  # Blueprint XML: Update {{<cm:property>}} names and {{{}$\{...{}}}} 
> references
>  # Java code: Update property lookups and constants
>  # Tests: Update property name references
> *System properties:*
>  # Old system properties in {{custom.system.properties}} become unused for 
> overrides
>  # They still work for variable substitution in {{.cfg}} files
>  # Can be removed or left for backward compatibility
> h3. Benefits
>  * *Fixes the problem:* Configuration Admin updates will work correctly
>  * *Backward compatible:* System properties still work for variable 
> substitution
>  * *No breaking changes:* Users don't need to update 
> {{custom.system.properties}}
>  * *Better readability:* Some properties become more readable (e.g., 
> {{{}updateProfileSegment.maxRetries{}}})
>  * *Self-documenting:* Domain-specific prefixes make configuration clearer
> h3. Impact Assessment
> ||Component||Impact Level||Files to Update||
> |Migration|Low|1 {{{}.cfg{}}}, 1 Java file|
> |Router|High|1 {{{}.cfg{}}}, 1 Blueprint XML (~15 references)|
> |Cluster|Medium|1 {{{}.cfg{}}}, 1 Blueprint XML (2 references)|
> |Plugins Base|Low|1 {{{}.cfg{}}}, 1 Blueprint XML, 1 Java file|
> |Services|Low|1 {{{}.cfg{}}}, 1 Blueprint XML (1 reference)|
> h2. Integration Test Analysis
> h3. Summary
> *Result:* None of the affected properties (excluding V2 compatibility mode) 
> are modified dynamically in integration tests using 
> {{{}updateConfiguration(){}}}.
> However, one test configuration file uses the old router property names and 
> will need to be updated when the renaming is implemented.
> h3. Properties Modified Dynamically in Tests
> h4. 1. V2CompatibilityModeIT.java (Already Fixed)
>  * *Properties:* {{{}v2.compatibilitymode.enabled{}}}, 
> {{v2.compatibilitymode.defaultTenantId}}
>  * *Status:* Already updated to use new property names
>  * *Impact:* None - already fixed
> h4. 2. RuleServiceIT.java
>  * *Property:* {{rules.optimizationActivated}} in 
> {{org.apache.unomi.services}}
>  * *Status:* NOT affected - this property is not in our conflict list
>  * *Impact:* None
> h4. 3. ProfileServiceIT.java
>  * *Property:* {{throwExceptions}} in {{org.apache.unomi.persistence.*}}
>  * *Status:* NOT affected - this is a persistence property, not in our 
> conflict list
>  * *Impact:* None
> h3. Properties NOT Modified Dynamically
> The following affected properties are *NOT* modified dynamically in 
> integration tests:
>  # *Migration:* {{recoverFromHistory}} - No tests modify this
>  # *Router:* All 13 properties ({{{}kafka.host{}}}, {{{}kafka.port{}}}, etc.) 
> - No tests modify these dynamically
>  # *Cluster:* {{{}nodeId{}}}, {{nodeStatisticsUpdateFrequency}} - No tests 
> modify these
>  # *Plugins Base:* {{maxProfilesInOneMerge}} - No tests modify this
>  # *Services:* {{segment.max.retries.update.profile.segment}} - No tests 
> modify this
> h3. Test Configuration Files That Need Updates
> h4. Router Test Configuration File
> *File:* {{itests/src/test/resources/org.apache.unomi.router.cfg}}
> *Current properties (OLD names):*
> {code:java}
> router.config.type=nobroker
> import.oneshot.uploadDir=${karaf.data}/tmp/unomi_oneshot_import_configs/
> executionsHistory.size=5
> executions.error.report.size=200
> config.allowedEndpoints=file,ftp,sftp,ftps
> {code}
> *Will need to be updated to (NEW names):*
> {code:java}
> router.config.type=nobroker
> router.import.oneshot.uploadDir=${karaf.data}/tmp/unomi_oneshot_import_configs/
> router.executionsHistory.size=5
> router.executions.error.report.size=200
> router.config.allowedEndpoints=file,ftp,sftp,ftps
> {code}
> *Note:* This file is used in {{BaseIT.java}} line 525:
> {code:java}
> replaceConfigurationFile("etc/org.apache.unomi.router.cfg", new 
> File("src/test/resources/org.apache.unomi.router.cfg")),
> {code}
> *Impact:* Low - Only need to update the test configuration file when 
> implementing the router property renaming.
> h3. Conclusion
> *Good News:* No integration tests are currently broken by the Karaf override 
> issue because:
>  * Tests don't dynamically modify the affected properties
>  * Tests that do modify properties use properties that are NOT affected
> *Action Required:* When implementing the router property renaming, update the 
> test configuration file 
> {{itests/src/test/resources/org.apache.unomi.router.cfg}} to use the new 
> property names with the {{router.}} prefix.
> h2. Testing Plan
> *Configuration Admin Tests:*
>  # Verify {{config:property-set}} and {{config:update}} work for each 
> affected component
>  # Verify changes are persisted and applied to components
>  # Verify {{@Modified}} methods receive updated values
>  
> *System Property Tests:*
>  # Verify system properties no longer override Configuration Admin
>  # Verify system properties still work for variable substitution in {{.cfg}} 
> files
>  *Integration Tests:*
>  # Run existing integration tests
>  # Add tests to verify Configuration Admin updates work correctly
>  # Update {{itests/src/test/resources/org.apache.unomi.router.cfg}} when 
> implementing router property renaming
> h2. Migration Notes
>  * *For Users:* No immediate action required. System properties in 
> {{custom.system.properties}} will continue to work for variable substitution.
>  * *For Administrators:* Configuration Admin commands will now work 
> correctly. Old system properties can be removed from 
> {{custom.system.properties}} if desired, but it's not required.
>  * *Documentation:* Update configuration documentation to reflect new 
> property names.
> h2. References
>  * Karaf Configuration Documentation: [Environment Variables & System 
> Properties|https://karaf.apache.org/manual/latest/#_environment_variables_system_properties]



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to