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)

Reply via email to