davsclaus opened a new pull request, #26810:
URL: https://github.com/apache/camel/pull/26810

   _Claude Code on behalf of Claus Ibsen (davsclaus)_
   
   JIRA: https://issues.apache.org/jira/browse/CAMEL-24976 (also fixes the root 
cause of CAMEL-21513)
   
   A deep review of the core type converter found several bugs. Each one was 
first reproduced against 4.23.0-SNAPSHOT. There is one commit per area:
   
   1. **Converting to a primitive returned the wrong wrapper type.** The fast 
path returned an `Integer` or `Long` as-is for *any* primitive target, so 
`convertTo(int.class, 5L)` returned a `Long` and callers got a 
`ClassCastException`. For example, a bean method with an `int` parameter failed 
with `argument type mismatch` when the body was a `Long`. Two smaller fixes in 
the same commit:
      - `tryConvertTo(boolean.class, ...)` no longer throws when the value 
cannot be converted.
      - The last-resort `Object` converter lookup now uses the wrapper type for 
primitive targets.
   2. **A recorded miss blocked conversions that could succeed.** Misses are 
cached per pair of classes, but fallback converters decide per value. So after 
one value failed, every later value of the same type returned `null`. Other 
problems in the same area:
      - a converter or fallback added after a miss was never used;
      - a miss on a super class blocked its sub classes;
      - `lookup()` returned the internal miss marker, so callers checking for 
`null` thought a converter existed.
   
      Now:
      - fallbacks are still tried for a pair that missed, but the super-type 
scans are still skipped;
      - misses are cleared when a converter or fallback is added;
      - the scans and `lookup()` skip misses;
      - a miss is recorded with `putIfAbsent`, so it cannot overwrite a 
converter added concurrently.
   3. **Super-type converter selection is now deterministic (CAMEL-21513).** 
The registry used to take the first match while iterating a 
`ConcurrentHashMap`, and that order can change between JVM runs. It now walks 
the value's type hierarchy breadth-first: at each level interfaces are tried 
before the super class, and `Object` is tried last. Each candidate is looked up 
directly, which is also cheaper than scanning every converter.
   4. **Number conversion fixes in `ObjectConverter`:**
      - `toNumber` threw for values below `Integer.MIN_VALUE`, returned a 
`Long` for `Integer.MAX_VALUE`, and did not accept exponent notation;
      - `toBigInteger` lost precision for `BigDecimal` and for large doubles;
      - `byte[]` to `char` sign-extended bytes above 127.
   5. **Smaller converter fixes:**
      - `TimeUnit.MICROSECONDS` is now supported;
      - String to `ByteBuffer` now uses the exchange charset (header or 
property);
      - converting an array to a `Set` no longer returns a `List`;
      - enum conversion prefers an exact match;
      - `FutureTypeConverter` restores the thread's interrupt flag.
   6. **Upgrade guide entry** (4.23) for the changed behavior.
   
   ### Not changed (known, left for follow-up)
   - **Cache growth:** the conversion cache holds `Class` references with no 
size limit, so dynamic or proxy classes keep adding entries and their class 
loaders stay loaded.
   - **`canPromote`:** since CAMEL-20051 every successful fallback is cached, 
so the flag no longer has any effect.
   - **Duplicate-converter policy:** generated bulk loaders register through 
`addConverter()`, which bypasses the `TypeConverterExists` policy.
   - **`tryAssignableFrom`** is still a full scan, and its result can still 
depend on iteration order. It only runs as the last resort, after the fallbacks.
   - **Silent numeric narrowing:** for example, `Long` to `Integer` overflows 
without an error. This is long-standing behavior.
   - **`Void.class` from `lookup()`:** a converter obtained through `lookup()` 
returns `Void.class` for an allowed null result. The registry needs this 
marker, so it was not changed.
   
   ### Tests
   - New `CoreTypeConverterRegistryTest`, plus additions to the existing 
converter tests.
   - The full camel-core suite passes: 7,504 tests. One test, 
`ErrorRegistrySourceLocationTest`, failed only because the local 
camel-base-engine jar was stale; it passes after reinstalling that module.
   - Tests also pass for camel-xml-jaxp, camel-jaxb, camel-jackson and 
camel-jsonpath.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to