Java Spring IntegrationFlow实现中的ClassCastException
我目前有一个IntegrationFlow实现,它利用一个服务类来实现流执行的所有所需功能。像这样的Java Spring IntegrationFlow实现中的ClassCastException,java,spring,spring-integration,spring-integration-dsl,Java,Spring,Spring Integration,Spring Integration Dsl,我目前有一个IntegrationFlow实现,它利用一个服务类来实现流执行的所有所需功能。像这样的 @Service public class FlowService { public Message<String> removeLineFeeds(Message<String> message) { return MessageBuilder .withPayload(StringUtils.remove(me
@Service
public class FlowService {
public Message<String> removeLineFeeds(Message<String> message) {
return MessageBuilder
.withPayload(StringUtils.remove(message.getPayload(), StringUtils.LF))
.copyHeadersIfAbsent(message.getHeaders())
.build();
}
}
@Configuration
@EnableIntegration
public class FlowConfiguration {
@Autowired
private FlowService flowService;
@Bean
public IntegrationFlow flow() {
return IntegrationFlows
.from("inputChannel")
.transform(flowService, "removeLineFeeds")
.get();
}
}
@Bean
public IntegrationFlow flow() {
return IntegrationFlows
.from("inputChannel")
.transform(flowService::removeLineFeeds)
.get();
}
不幸的是,当以这种方式实现时,流在处理消息时将抛出ClassCastException
。我已经尝试了一些目前存在于网络上的不同的解决方案,但似乎没有一个能奏效。无论使用什么IntegrationFlow方法(转换、过滤等),我都会遇到类似的问题
当前实现需要更改哪些内容,以允许在IntegrationFlow方法中使用flowService::removeLineFeeds
编辑:根据ARTEM的回复
似乎是集成流中的一个简单转换器完成了这个任务。我当前的实现似乎是以消息
的形式传递消息,而不是我期望的消息
。有关更多详细信息,请参见下文Artem的完整回复
@Bean
public IntegrationFlow flow() {
return IntegrationFlows
.from("inputChannel")
.convert(String.class)
.transform(flowService::removeLineFeeds)
.get();
}
关键是lambda必须对应于某个功能接口。 在
transform()
的情况下,它是一个通用变压器
。实际上,您的Message removeLineFeeds(Message Message)
满足了这样一个契约。如果您只处理有效负载,那么它会工作得很好:
public String removeLineFeeds(String message) {
return StringUtils.remove(message.getPayload(), StringUtils.LF);
}
因为当目标实现中的所有通用信息在运行时被擦除时,我们猜不出您想要处理整个消息
,所以框架只会向lambda传播一个有效负载。您的字符串
无法转换为消息
,因此出现了类别异常
为了解决这个问题并模拟Java泛型系统,我们建议使用一个具有显式预期类型的重载方法:
/**
* Populate the {@link MessageTransformingHandler} instance for the provided
* {@link GenericTransformer} for the specific {@code payloadType} to convert at
* runtime.
* @param payloadType the {@link Class} for expected payload type. It can also be
* {@code Message.class} if you wish to access the entire message in the transformer.
* Conversion to this type will be attempted, if necessary.
* @param genericTransformer the {@link GenericTransformer} to populate.
* @param <P> the payload type - 'transform from' or {@code Message.class}.
* @param <T> the target type - 'transform to'.
* @return the current {@link BaseIntegrationFlowDefinition}.
* @see MethodInvokingTransformer
* @see LambdaMessageProcessor
*/
public <P, T> B transform(Class<P> payloadType, GenericTransformer<P, T> genericTransformer) {
通过这种方式,我们可以说是一个框架,我们希望得到一个完整的消息,以便我们的函数进行处理
无论如何,我更喜欢第一个变量,它只包含一个有效负载:框架将为您处理应答消息中的请求头
请参阅文档中的更多信息:谢谢您的回复。我尝试了上述两种解决方案,但仍然遇到了ClassCastException。更具体地说,异常现在读取java.lang.ClassCastException:[B不能转换为java.lang.String
。好吧,这已经是一个不同的异常,与业务相关。您需要一个字符串
,但您的消息包含一个字节[]
作为有效负载。您可以从该字节[]创建一个字符串
在transformer方法中,或者使用convert(String.class)
并注册一个Converter
@IntegrationConverter
bean。看起来添加了.convert(String.class)就成功了。如果我使用.transform(flowService,“removeLineFeeds”),我的假设正确吗
Spring Integration为我处理转换?试图理解我在最初的实现中如何没有遇到这个问题。这是正确的。因为通过方法名调用会在反射中着陆,我们可以尝试将传入数据转换为预期类型。使用lambda,我们只有一个直接调用,没有人能够猜到e转换的目标类型,除非您将该重载方法与类一起使用。。。
.transform(Message.class, flowService::removeLineFeeds)