即使在 @Converter 注释中将 allowNull 设置为 true,Camel TypeConverter 仍会抛出 NoTypeConversionAvailableException
Camel TypeConverter still throws NoTypeConversionAvailableException even if allowNull set to true in @Converter annotation
我正在使用 Apache Camel 3.4.3 并尝试为我的骆驼路线转换空值
from(endpointURI)
.convertBodyTo(DataContainer.class)
.to(DIRECT_ROUTE)
像这样使用自定义 TypeConverter:
@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);
}
但这种方式会引发异常:
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 ]
开始调试,发现当@Converter注解中的allowNull设置为true, 这导致在方法 public <T> T mandatoryConvertTo(Class<T> type, Exchange exchange, Object value) throws NoTypeConversionAvailableException
:
中执行以下代码到 CoreTypeConverterRegistry
class
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;
}
此处的 answer 为空,下一步抛出 NoTypeConversionAvailableException。
但是 Apache Camel 接下来说 (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
所以我的问题是我如何 return null (我可以这样做)类型转换器中的值,这样我的路线就不会在转换发生了吗?
我 运行 遇到了同样的问题,最后做了 doTry()
并且特别优雅地捕捉到了 NoTypeConversionAvailableException
.
示例转换器:
@Converter(generateLoader = true)
public final class TestConverter {
@Converter(allowNull = true)
public static MyObject parse(String message) {
if (!StringUtils.hasText(message)) {
return null;
}
MyObject obj = new MyObject();
obj.setMyFirstProperty(message.substring(10, 11));
// Set other fields, etc.
return obj;
}
}
示例路线(使用 generateLoader = true
参数时自动使用 Camel TypeConverterRegistry
中的 @Converter
:
from("direct:test")
.log(LoggingLevel.DEBUG, logger, "${body}")
.doTry()
.bean(myService, "processTheMessage")
.doCatch(NoTypeConversionAvailableException.class)
.end();
这不是我最喜欢的解决方案,因为 allowNull
是 Camel 文档中记录的功能,但它允许我优雅地丢弃
这是因为convertBodyTo
使用了强制转换,这意味着如果不能转换就会抛出异常。
您可以争辩说 allowNull
即使对于强制转换也应该有效。然而,这不是它的原始设计,因为它是用于常规转换(不是强制性的)。作为强制性的是保证始终存在该给定类型的响应对象(它永远不会为空)的合同。
还引入了 allowNull
,当您有后备转换器时,这些转换器可能会或可能无法转换,具体取决于输入数据的内容。
需要多考虑一下,我们是应该放宽 convertBodyTo
为非强制性,还是添加一个标志以便您可以打开|关闭强制性
我正在使用 Apache Camel 3.4.3 并尝试为我的骆驼路线转换空值
from(endpointURI)
.convertBodyTo(DataContainer.class)
.to(DIRECT_ROUTE)
像这样使用自定义 TypeConverter:
@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);
}
但这种方式会引发异常:
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 ]
开始调试,发现当@Converter注解中的allowNull设置为true, 这导致在方法 public <T> T mandatoryConvertTo(Class<T> type, Exchange exchange, Object value) throws NoTypeConversionAvailableException
:
CoreTypeConverterRegistry
class
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;
}
此处的 answer 为空,下一步抛出 NoTypeConversionAvailableException。
但是 Apache Camel 接下来说 (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
所以我的问题是我如何 return null (我可以这样做)类型转换器中的值,这样我的路线就不会在转换发生了吗?
我 运行 遇到了同样的问题,最后做了 doTry()
并且特别优雅地捕捉到了 NoTypeConversionAvailableException
.
示例转换器:
@Converter(generateLoader = true)
public final class TestConverter {
@Converter(allowNull = true)
public static MyObject parse(String message) {
if (!StringUtils.hasText(message)) {
return null;
}
MyObject obj = new MyObject();
obj.setMyFirstProperty(message.substring(10, 11));
// Set other fields, etc.
return obj;
}
}
示例路线(使用 generateLoader = true
参数时自动使用 Camel TypeConverterRegistry
中的 @Converter
:
from("direct:test")
.log(LoggingLevel.DEBUG, logger, "${body}")
.doTry()
.bean(myService, "processTheMessage")
.doCatch(NoTypeConversionAvailableException.class)
.end();
这不是我最喜欢的解决方案,因为 allowNull
是 Camel 文档中记录的功能,但它允许我优雅地丢弃
这是因为convertBodyTo
使用了强制转换,这意味着如果不能转换就会抛出异常。
您可以争辩说 allowNull
即使对于强制转换也应该有效。然而,这不是它的原始设计,因为它是用于常规转换(不是强制性的)。作为强制性的是保证始终存在该给定类型的响应对象(它永远不会为空)的合同。
还引入了 allowNull
,当您有后备转换器时,这些转换器可能会或可能无法转换,具体取决于输入数据的内容。
需要多考虑一下,我们是应该放宽 convertBodyTo
为非强制性,还是添加一个标志以便您可以打开|关闭强制性