CAMEL-23999/CAMEL-24000: camel-spring-boot - Spring Boot 4 idiom alignment and configuration metadata regression fix#1843
Conversation
…ce with run-controller enabled With camel.main.run-controller=true, MainListener beans were notified twice for beforeStart/afterStart (and beforeStop/afterStop): once via the controller created by CamelAutoConfiguration (the complete callback stream added in CAMEL-21359) and once more via the run controller's internal Main, which registered the same listener beans and fires the start/stop callbacks from MainSupport.run(). The run controller's Main is only used to keep the JVM running, so it no longer registers the MainListener beans. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…iguration - HierarchicalCondition and CompositeConversionService are referenced by nothing in the repository - ClusteredRouteControllerConfiguration.clusterServiceRef has no accessors, so it can never be bound nor read - unused ConditionalOnAvailableEndpoint import in CamelDevConsoleAutoConfiguration Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…roperties beans The trace, error registry and security policy auto-configurations applied dev/prod profile defaults by mutating the injected @ConfigurationProperties singleton, so any other bean reading the same properties observed the mutated values instead of what the user configured. Compute the effective values locally instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…r route controller auto-configurations Replace @ConditionalOnProperty(name = "enabled") with the clearer @ConditionalOnBooleanProperty (Spring Boot 3.4+) on the supervising and clustered route controller auto-configurations, and drop the redundant in-method isEnabled() re-check and the discouraged null @bean return in SupervisingRouteControllerAutoConfiguration (the class-level condition already guarantees the property is true). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ocessor execution The maven-compiler-plugin 3.15.0 upgrade (apache#1648) silently stopped running annotation processors discovered on the compile classpath (behaviour change in maven-compiler-plugin 3.13+). As a result the camel-spring-boot core and all starter jars no longer contained META-INF/spring-configuration-metadata.json, breaking IDE completion for camel.* properties and the generated src/main/docs/*.json property documentation. Configure <proc>full</proc> to restore processor execution. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s and guard against option drift Replace the eight hand-written per-field copy chains in the vault auto-configurations with BeanUtils.copyProperties (all properties mirror the Camel core vault configurations by name and type), and add a reflection test that fails when Camel core gains a vault option the starter properties class does not expose. The new test immediately found real drift: camel.vault.ibm.refresh-enabled and camel.vault.ibm.secrets existed in Camel core but could not be configured from Spring Boot. Add both properties and regenerate spring-boot.json. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e.Duration Convert the raw millisecond long/int properties of the supervising route controller (initial-delay, back-off-delay, back-off-max-delay, back-off-max-elapsed-time) and the startup conditions (interval, timeout) to java.time.Duration with @DurationUnit(MILLIS). Existing plain-number values keep meaning milliseconds; users can now also write readable values such as 5s or 2m. The clustered route controller initial-delay keeps its String type on purpose: it accepts Camel time patterns (via TimePatternConverter) that Duration binding does not support, so converting it would break existing configurations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
davsclaus
left a comment
There was a problem hiding this comment.
Claude Code on behalf of Claus Ibsen (@davsclaus)
Nice work, Federico — this is a well-structured PR with clear atomic commits and good test coverage. The git history confirms all changes are consistent with prior intent (none revert intentional decisions), and the MainListener exactly-once fix addresses a genuine bug from CAMEL-21359.
Confirmed findings
1. Narrowing cast (int) Duration.toMillis() — potential overflow (Low)
In CamelAutoConfiguration.java, Duration.toMillis() returns long; casting to int silently wraps for values > ~24.8 days. The defaults (500ms, 20s) make this safe in practice, but Math.toIntExact() would turn a misconfiguration into a clear ArithmeticException instead of silent wraparound.
2. Missing upgrade guide entry for property type changes (Medium)
The getter/setter types on SupervisingRouteControllerConfiguration (long → Duration) and CamelStartupConditionConfigurationProperties (int → Duration) are public API changes. @DurationUnit(MILLIS) ensures backward compatibility for plain numeric values in application.properties, but code calling e.g. config.getBackOffDelay() and expecting a long will fail to compile. An upgrade guide entry documenting the type changes would be appropriate.
Observations (non-blocking)
@ConditionalOnBooleanPropertysemantic tightening: the old@ConditionalOnProperty(name = "enabled")matched any value except"false"; the new annotation only matches"true"(case-insensitive). Correct behavior for a boolean flag, but technically a subtle change.BeanUtils.copyPropertiesfor vault configs: clean simplification, and the newVaultConfigurationPropertiesMappingTestis an excellent drift guard.- Dead code removals (
CompositeConversionService,HierarchicalCondition,clusterServiceRef): verified — no references anywhere in the repo. - IBM vault drift fix (
refreshEnabled,secrets): confirmed genuine missing configuration.
This review does not replace specialized tools like CodeRabbit, Sourcery, or SonarCloud.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
| scs.setInterval((int) config.getInterval().toMillis()); | ||
| scs.setTimeout((int) config.getTimeout().toMillis()); |
There was a problem hiding this comment.
Minor: Duration.toMillis() returns long; the (int) cast silently wraps for large values. Consider using Math.toIntExact() to fail fast on misconfiguration instead of silent overflow:
| scs.setInterval((int) config.getInterval().toMillis()); | |
| scs.setTimeout((int) config.getTimeout().toMillis()); | |
| scs.setInterval(Math.toIntExact(config.getInterval().toMillis())); | |
| scs.setTimeout(Math.toIntExact(config.getTimeout().toMillis())); |
There was a problem hiding this comment.
Applied in 25b33d8 — switched to Math.toIntExact() for both interval and timeout. Thanks!
Claude Code on behalf of Federico Mariani.
…ad of silent int wraparound Address review feedback: use Math.toIntExact instead of a narrowing cast when converting the startup condition interval/timeout Durations to millis. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Both review findings addressed:
Claude Code on behalf of Federico Mariani. |
Claude Code on behalf of Federico Mariani (@Croway)
Resolves CAMEL-23999 and CAMEL-24000.
Modernization of
core/camel-spring-bootfollowing a review against Spring Boot 4.1.x best practices, plus one build regression fix found along the way.CAMEL-23999 — restore
spring-configuration-metadata.json(regression)The maven-compiler-plugin 3.15.0 upgrade (#1648) silently stopped running annotation processors discovered on the compile classpath (behaviour change in maven-compiler-plugin 3.13+). As a result the core and all starter jars were built without
META-INF/spring-configuration-metadata.json— breaking IDE completion for everycamel.*property — and the generatedsrc/main/docs/*.jsonfiles could no longer be regenerated. Fixed with<proc>full</proc>in the root POM; verified the metadata is back in both the core jar and a starter jar.CAMEL-24000 — Spring Boot 4 idiom alignment
MainListenerbeans notified exactly once withcamel.main.run-controller=true. They previously receivedbeforeStart/afterStart(and the stop callbacks) twice: once from the controller created byCamelAutoConfiguration(the complete callback stream added in CAMEL-21359) and once more from the run controller's internalMain. The run controller no longer registers the listener beans. A new test (CamelMainListenerRunControllerTest) asserts exactly-once delivery for all seven callbacks — it was written first and demonstrated the duplication (beforeStart=2, afterStart=2) before the fix.HierarchicalConditionandCompositeConversionService(referenced by nothing),ClusteredRouteControllerConfiguration.clusterServiceRef(no accessors, never bindable), unused import inCamelDevConsoleAutoConfiguration.@ConfigurationPropertiesbeans: the trace, error registry and security policy auto-configurations applied dev/prod profile defaults by mutating the injected singleton, so other beans reading the same properties observed altered values. Effective values are now computed locally.@ConditionalOnBooleanProperty(Spring Boot 3.4+) replaces@ConditionalOnProperty(name = "enabled")on the supervising and clustered route controller auto-configurations; the redundant in-methodisEnabled()re-check and null@Beanreturn are gone.BeanUtils.copyProperties(all properties mirror the Camel core vault configurations by name and type), guarded by a new reflection test that fails when Camel core gains a vault option the starter does not expose. The test immediately found real drift:camel.vault.ibm.refresh-enabledandcamel.vault.ibm.secretsexisted in Camel core but could not be configured from Spring Boot — both added andspring-boot.jsonregenerated.java.time.Durationwith@DurationUnit(MILLIS): supervising route controllerinitial-delay/back-off-delay/back-off-max-delay/back-off-max-elapsed-timeand startup conditioninterval/timeout. Plain numeric values keep meaning milliseconds (existing tests binding plain numbers pass unchanged); readable values like5snow work too.Compatibility notes
long/int→Duration); these classes are starter-internal but technically public API.initial-delaydeliberately keeps itsStringtype +TimePatternConverter: it accepts Camel time patterns (e.g.10 seconds) thatDurationbinding does not support, so converting it would break existing configurations.@Beanreturns in the trace/errorregistry/threadpool/routetemplate auto-configurations were kept: their conditions depend on the runtime Camel profile or on "any property under the prefix" semantics, which cannot be expressed declaratively.Testing
mvn verifyoncore/camel-spring-bootpasses (full suite + ITs).CamelMainListenerRunControllerTest(exactly-once listener callbacks),VaultConfigurationPropertiesMappingTest(vault option drift guard).🤖 Generated with Claude Code
Review follow-ups
Math.toIntExact()instead of(int)cast when converting the startup condition interval/timeout to millis, so overflow fails fast (review feedback).Durationproperty type changes: CAMEL-24000: camel-spring-boot - upgrade guide entry for Duration configuration properties camel#24593.