[ 
https://issues.apache.org/jira/browse/CAMEL-24501?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18110648#comment-18110648
 ] 

Federico Mariani commented on CAMEL-24501:
------------------------------------------

PR: https://github.com/apache/camel-spring-boot/pull/1935

Items 1 and 3 are implemented and the ~425 starters regenerated (746 files).

*Item 1* - the generated converters now delegate to a new
{{org.apache.camel.spring.boot.util.BeanReferenceHelper}}. It resolves 
{{#bean:id}}, {{#id}}, a plain bean id,
{{#autowired}} and {{#type:fqn}}, and throws {{IllegalArgumentException}} 
naming the value, the target type and
the configuration prefix when the value cannot be resolved. The per-type 
{{switch}} is gone, so the branch that
returned null for an unlisted target type is gone with it.

*Item 3* - the generated customizers call a new 
{{CamelPropertiesHelper.copyConfigurationProperties}}, which
strips the auto configuration layer options ({{enabled}}, {{customizer}}) 
before binding, fails when an option
the application configured itself cannot be set, and logs at DEBUG when an 
option that only carries its catalog
default cannot be set. {{camel.springboot.lenient-configuration-binding=true}} 
logs at WARN and continues instead.

Blanket {{failIfNotSet=true}} was implemented first and had to be backed out: 
because item 2 materialises every
catalog default as a field initializer, the customizer copies defaults for 
options that were never bindable. The
clearest case is {{camel-core-starter}}, where {{camel.language.simple.trim}}, 
{{pretty}}, {{trimResult}} and
{{nested}} are options of the expression model rather than of 
{{SimpleLanguage}} and carry defaults - strict
binding would abort startup for every application with {{camel-core-starter}} 
on the classpath. Failing only on
options the application actually set closes the reported hole without that.

*Deferred, ticket left open:*

* *Item 2* (catalog defaults as literal field initializers). Not a local 
change: the generated getters returning
  the defaults are effectively public API, and 
{{spring-configuration-metadata.json}} derives {{defaultValue}}
  from the field initializers, so both IDE completion and the generated starter 
{{.adoc}} pages (built by the
  readme mojo from that metadata) would lose every default. The alternative - 
having the customizer skip a value
  equal to the catalog default - makes it impossible to set an option back to 
its default explicitly. It needs
  its own change with the metadata and docs generation adjusted at the same 
time, and it is the prerequisite for
  turning the strictness above into blanket {{failIfNotSet=true}}.
* Restricting the generated converters to {{camel.*}} property sources.
  {{ConditionalGenericConverter.matches}} only receives the source and target 
{{TypeDescriptor}}, never the
  property name, so the only way to make it selective is to annotate every 
complex typed field on the ~425
  generated configuration classes with a marker the converter tests for. Best 
done together with a change that
  touches those classes anyway.

An upgrade guide entry for {{camel-4x-upgrade-guide-4_23.adoc}} in apache/camel 
has been written and will be
raised separately.

_Comment added by Claude Code on behalf of Federico Mariani._

> camel-spring-boot-generator-maven-plugin - generated configuration binding 
> drops values silently in three places
> ----------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24501
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24501
>             Project: Camel
>          Issue Type: Improvement
>          Components: tooling
>            Reporter: Andrea Cosentino
>            Assignee: Federico Mariani
>            Priority: Major
>             Fix For: 4.23.0
>
>
> Three related spots in {{SpringBootAutoConfigurationMojo}} generate code that 
> discards configuration instead of reporting it. All three regenerate into the 
> ~425 starters.
> *1. Converters return null for unresolved references (line 1488)*
> {code:java}
> sb.append("String ref = source.toString();\n");
> sb.append("if (!ref.startsWith(\"#\")) {\n");
> sb.append("    return null;\n");
> sb.append("}\n");
> {code}
> A configured value that does not start with {{#}} converts to null, as does 
> one whose target type is not in the generated switch. For options holding 
> objects such as {{sslContextParameters}}, a typo in the property value yields 
> a null rather than an error, and the component starts with the option unset.
> *2. Catalog defaults emitted as literal field initializers (line 747)*
> {code:java}
> if (!isBlank(option.getDefaultValue())) {
>     if ("java.lang.String".equals(option.getJavaType())) {
>         
> prop.getField().setStringInitializer(option.getDefaultValue().toString());
>     } else if ...
>         
> prop.getField().setLiteralInitializer(option.getDefaultValue().toString());
> {code}
> Every defaulted catalog option becomes a non-null field on the configuration 
> class. The generated customizer then copies the whole configuration onto the 
> component, so a value set programmatically before the customizer runs is 
> overwritten by the materialised default. The wrapper-type/null-sentinel 
> design elsewhere suggests defaults were meant to live in 
> {{spring-configuration-metadata}} {{defaultValue}} for IDE display only.
> *3. Customizer bodies bind with failIfNotSet=false (line 1825)*
> {{createComponentBody}} emits {{CamelPropertiesHelper.copyProperties(...)}}, 
> which calls {{setCamelProperties(..., failIfNotSet=false)}}. An option that 
> cannot be bound is dropped without a log line. The generated {{camel.rest.*}} 
> path uses {{true}} for the same operation, so the two disagree.
> *Proposal*
> - Make the converter throw {{IllegalArgumentException}} naming the option and 
> the expected {{#bean:}} syntax when a non-null value does not resolve, and 
> make the generated converters {{ConditionalGenericConverter}} instances that 
> match only {{camel.*}} property sources.
> - Stop emitting literal initializers for defaulted options, or have the 
> customizer skip values equal to the catalog default.
> - Use {{failIfNotSet=true}} in the generated customizer bodies, or at minimum 
> log at WARN with the option name when a bind is missed.
> These are best done as one change followed by a regeneration pass, since the 
> third will surface any latent generator or catalog drift as startup failures 
> - which is the intent.
> ----
> _This issue was drafted by Claude Code on behalf of Andrea Cosentino._



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

Reply via email to