Skip to content
Advertisement

Camel TypeConverter still throws NoTypeConversionAvailableException even if allowNull set to true in @Converter annotation

I’m using Apache Camel 3.4.3 and trying to convert empty value for my camel route

     from(endpointURI)
        .convertBodyTo(DataContainer.class)
        .to(DIRECT_ROUTE)

with custom TypeConverter like this:

@Converter(allowNull = true)
public DataContainer toDataContainer(String xml) {
    LOGGER.info("Received body as string [{}] try to convert to DataContainer", xml);
    if (StringUtils.isBlank(xml)) {
        return null;
    }
    if (!XmlUtils.isXml(xml)) {
        throw new SwiftCorpException(ErrorCode.ERROR_99999,
            String.format(
                "value [%s] is not a xml, so it cannot be converted to DataContainer",
                xml
            )
        );
    }
    return DataContainer.fromXml(xml);
}

but this way fires exception:

org.apache.camel.InvalidPayloadException: No body available of type: ru.swiftcorp.common.utils.DataContainer but has value: of type: java.lang.String on: Message. Caused by: No type converter available to convert from type: java.lang.String to the required type: ru.vtb.swiftcorp.common.utils.DataContainer with value . Exchange[]. Caused by: [org.apache.camel.NoTypeConversionAvailableException – No type converter available to convert from type: java.lang.String to the required type: ru.swiftcorp.common.utils.DataContainer with value ]

I started debugging, and found out when allowNull in @Converter annotation setted to true, this leads to the execution of the following code into CoreTypeConverterRegistry class inside method public <T> T mandatoryConvertTo(Class<T> type, Exchange exchange, Object value) throws NoTypeConversionAvailableException:

public <T> T mandatoryConvertTo(Class<T> type, Exchange exchange, Object value) throws NoTypeConversionAvailableException {

    ...
    Object answer = doConvertTo(type, exchange, value, true, false);
    if (answer == null) {
        // Could not find suitable conversion
        throw new NoTypeConversionAvailableException(value, type);
    }
    return (T) answer;
}

here’s answer is null and next step NoTypeConversionAvailableException throws.

But Apache Camel says next (here’s a link) :

If null should be allowed as a valid response, then from Camel 2.11.2/2.12 onwards you can specify this in the annotation as shown

So my question is how i can return null (and can I do this) value in type converter so that my route does not break in the place where the conversion takes place?

Advertisement

Answer

This is because convertBodyTo is using mandatory conversion, which means that an exception will be thrown if it was not possible to converter.

You can argue that allowNull even for mandatory conversion should be valid. However that was not its original design, as it was for regular conversion (not mandatory). As mandatory is a contract that guarantees that there is always a response object of that given type (its never null).

Also allowNull was introduced when you have fallback converters that may or may not be able to convert depending on the content of the input data.

Need to think a bit more about this, whether we should either relax convertBodyTo to be non mandatory, or add a flag so you can turn mandatory on|off

Advertisement