Nathan created CAMEL-21513:
------------------------------
Summary: CoreTypeRegistry can create unpredictable type to
converter mappings
Key: CAMEL-21513
URL: https://issues.apache.org/jira/browse/CAMEL-21513
Project: Camel
Issue Type: Improvement
Components: camel-core
Affects Versions: 4.4.4
Reporter: Nathan
*Context*
The CoreTypeConverterRegistry uses a map of converters to find a converter for
a TypeConvertible<from,to>.
If there is no known converter it attempts to find one in the existing
converter map based on the idea that an existing converter on a super class can
be used.
This logic is contained in the TypeResolverHelper.tryMatch method. The tryMatch
method will do an exhaustive search on the types in the converter and the super
classes of the to convert value.
To do this tryMatch will iterate over all the existing converters. Each
existing converter<from,to> will then be compared to the super classes of the
TypeConvertible<from,to>.
*Problem*
The problem is that the TypeResolverHelper.tryMatch can be highly random in
selecting a converter. The first converter that matches is chosen and stored
for all future usage of this specific type conversion.
But the order of iteration for the converter map is not guaranteed to be the
same every time. It is very likely that it is different for every load, since
it depends on the order that converters have been added and there is no order
guarantee on HashMap entry set iteration.
This is not only theoretical, we already had a problem with the type conversion
of DeferredElementNSImpl to CxfPayload. DeferredElementNSImpl implements both
org.w3c.dom.Element and org.w3c.dom.NodeList. Both of those have converters in
the CxfPayloadConverterLoader.
But the converter chosen was random and often changed after application
restarts. This caused problems for us since the NodeList to CxfPayload did not
transform the DeferredElementNSImpl as expected.
*Workaround*
There is an easy workaround by defining your own converters to ensure the
correct conversion happens, but this workaround can be cumbersome for
applications with a lot of implicit type conversions.
Especially if the correct conversion does exist, but is just not used.
*Solution?*
I do think there is a potential solution, the converter iteration is random and
it would be inefficient to order it. That would also not necessarily fix
anything since any order could be wrong for some specific conversion.
Instead the TypeResolverHelper.tryMatch could change things by iterating over
the super classes of the from first. And try to find a converter for each super
class.
The complication is that the super class iteration is done in the
TypeConvertible, so it would have to be duplicated or moved into the
TypeResolverHelper to do that.
The method getInterfaces that is used in the TypeConvertible is ordered by the
JDK, so there would be no randomness. Instead it would select the first
existing converter that is actually closest to the target class.
This is much better than just the first converter that happens to match with an
interface removed 5 super classes.
For the DeferredElementNSImpl it would then go:
look for DeferredElementNSImpl -> not found
look for ElementNSImpl -> not found
look for ElementImpl -> not found
Look for Element -> found CxfPayloadConverter.elementToCxfPayload
--
This message was sent by Atlassian Jira
(v8.20.10#820010)