Camel中MultipartEntityBuilder转InputStream失败,死信通道存文件异常
解决Camel死信通道中MultipartFormEntity转InputStream的问题
看起来你的死信通道无法正常存储失败请求的文件,核心问题是Camel默认没有提供MultipartFormEntity到InputStream的类型转换器,而文件组件需要后者来写入文件。这里有几个实用的解决方案,按推荐程度排序:
方案1:在死信通道的错误预处理中恢复原始文件流
最稳妥的方式是在死信通道处理失败消息前,把消息体换回最初的文件输入流——毕竟你本来就是要上传一个本地文件,原始文件的流或引用肯定可以在Exchange中保留。
你可以给死信通道添加onPrepareFailure处理器,在消息被送到file组件前重置消息体:
.errorHandler(deadLetterChannel("file:/home/r2/Desktop/ofBizFile/errorFinalServer") .asyncDelayedRedelivery() .maximumRedeliveries(3) .redeliveryDelay(1000) .retryAttemptedLogLevel(LoggingLevel.WARN) // 新增:预处理失败消息,恢复原始文件流 .onPrepareFailure(new Processor() { @Override public void process(Exchange exchange) throws Exception { // 假设你在ProcessorSetFileRequest里把原始文件的InputStream存在了名为"OriginalFileStream"的header中 InputStream originalStream = exchange.getIn().getHeader("OriginalFileStream", InputStream.class); if (originalStream != null) { exchange.getIn().setBody(originalStream); // 同时设置文件名header,保证死信文件的名称正确 exchange.getIn().setHeader(Exchange.FILE_NAME, "orders-02-01-2018.csv"); } } }) )
如果你的ProcessorSetFileRequest里还没保存原始文件信息,那修改这个处理器,在构建MultipartEntity的同时把原始文件的流或对象存到Exchange中:
// 在ProcessorSetFileRequest的process方法内 File originalFile = new File("你的原始文件路径/orders-02-01-2018.csv"); InputStream fileStream = new FileInputStream(originalFile); // 把原始流存入header,方便后续错误处理调用 exchange.getIn().setHeader("OriginalFileStream", fileStream); // 继续构建MultipartEntity MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addBinaryBody("file", fileStream, ContentType.DEFAULT_BINARY, originalFile.getName()); exchange.getIn().setBody(builder.build());
方案2:自定义类型转换器
如果不想修改现有预处理逻辑,可以给Camel添加一个自定义类型转换器,让它自动完成MultipartFormEntity到InputStream的转换:
- 编写转换器类:
import org.apache.camel.Converter; import org.apache.http.entity.mime.MultipartFormEntity; import java.io.InputStream; @Converter public class MultipartFormEntityConverter { @Converter public static InputStream toInputStream(MultipartFormEntity entity) throws Exception { // 直接提取MultipartFormEntity的内容流 return entity.getContent(); } }
- 在Camel上下文中注册这个转换器:
如果用Java DSL:
CamelContext context = new DefaultCamelContext(); context.getTypeConverterRegistry().addTypeConverter(InputStream.class, MultipartFormEntity.class, new MultipartFormEntityConverter());
如果用Spring XML配置:
<bean id="multipartConverter" class="你的包名.MultipartFormEntityConverter"/> <camelContext xmlns="http://camel.apache.org/schema/spring"> <typeConverters> <ref bean="multipartConverter"/> </typeConverters> <!-- 你的路由配置 --> </camelContext>
这样Camel在需要转换类型时,就会自动调用这个转换器完成转换。
问题根源说明
你的路由中,ProcessorSetFileRequest把消息体设置成了MultipartFormEntity,当HTTP请求失败进入死信通道时,file组件尝试将这个实体写入文件,但Camel默认没有提供该类型到InputStream的转换规则,因此抛出了NoTypeConversionAvailableException。
内容的提问来源于stack exchange,提问作者Rajat.r2
相关产品推荐
相关产品推荐

