[英]How do I return a value from a method in Spring Integration and not interrupt the original Message flow?
The encode
method of the fileProcessor
bean is responsible for encoding a video file. fileProcessor
bean的encode
方法负责编码视频文件。 If it encounters a problem the file should not be deleted, otherwise if everything is well, it is okay to delete. 如果遇到问题,则不应删除该文件,否则如果一切正常,则可以删除。 Right now, the only way to preserve the
Message
flow without changing the payload is to make the encode
method return void
. 现在,在不更改有效负载的情况下保留
Message
流的唯一方法是使encode
方法返回void
。 I need to return some 'header' information though so that SI
can later delete the file. 我需要返回一些“标题”信息,以便
SI
以后可以删除该文件。 I tried using MessageBuilder
to create a Message<File>
and return that, but when it arrives in the next channel it has been wrapped and there is a Message
inside a Message
, therefore my expression doesn't work to trigger the delete. 我尝试使用
MessageBuilder
创建一个Message<File>
并返回它,但是当它到达下一个通道时它已被包装并且Message
有一条Message
,因此我的表达式无法触发删除。
I suppose I could use a wrapped Message
and dig down one level in the object graph, but that seems clunky. 我想我可以使用一个包装的
Message
并在对象图中挖掘一个级别,但这看起来很笨拙。
What is the best approach to tacking on some return value without destroying the original Message payload and without polluting my POJO encode method with SI channels and sending? 在不破坏原始Message有效负载且不使用SI通道和发送方式污染我的POJO编码方法的情况下,获取某些返回值的最佳方法是什么?
Here is my configuration: 这是我的配置:
<!-- ########################## -->
<!-- ### Encoding ### -->
<!-- ########################## -->
<file:inbound-channel-adapter
directory="${paths.encode}"
channel="encodeChannel"
filename-regex="${encode.regex}"
prevent-duplicates="false">
<int:poller fixed-rate="5000"/>
</file:inbound-channel-adapter>
<int:service-activator
input-channel="encodeChannel"
output-channel="encodeResultChannel"
ref="fileProcessor"
method="encode">
</int:service-activator>
<!-- This is where I'm having trouble. -->
<!-- I don't expect this router to work. -->
<int:router
input-channel="encodeResultChannel"
expression="payload">
<int:mapping value="true" channel="encodeDeleteChannel"/>
<int:mapping value="false" channel="stdout"/>
</int:router>
<int:service-activator
input-channel="encodeDeleteChannel"
expression="payload.delete()"
output-channel="stdout">
</int:service-activator>
<stream:stdout-channel-adapter
id="stdout"
append-newline="true" />
edit: 编辑:
I'm using: 我正在使用:
<properties>
<spring-framework.version>3.2.3.RELEASE</spring-framework.version>
</properties>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
</dependency>
edit2: EDIT2:
here's the updated configuration 这是更新的配置
<!-- ########################## -->
<!-- ### Encoding ### -->
<!-- ########################## -->
<file:inbound-channel-adapter
directory="${paths.encode}"
channel="filePickupChannel"
filename-regex="${encode.regex}"
prevent-duplicates="false">
<int:poller fixed-rate="5000"/>
</file:inbound-channel-adapter>
<int:header-enricher
input-channel="filePickupChannel"
output-channel="encodeChannel">
<int:header name="origFile" expression="payload"/>
</int:header-enricher>
<int:service-activator
input-channel="encodeChannel"
output-channel="encodeResultChannel"
ref="fileProcessor"
method="encode">
</int:service-activator>
<int:router
input-channel="encodeResultChannel"
ignore-send-failures="false"
default-output-channel="stdout"
expression="payload">
<int:mapping value="true" channel="encodeDeleteChannel"/>
<int:mapping value="false" channel="stdout"/>
</int:router>
<int:service-activator
input-channel="encodeDeleteChannel"
expression="headers['origFile'].delete()"
output-channel="stdout">
</int:service-activator>
What version of Spring Integration and Spring Framework are you using? 您使用的是什么版本的Spring Integration和Spring Framework?
What does the signature of fileProcessor.encode()
look like? fileProcessor.encode()
的签名是什么样的?
You should not get a nested Message<?>
, the AbstractReplyProducingMessageHandler
has the following logic... 你不应该得到一个嵌套的
Message<?>
, AbstractReplyProducingMessageHandler
有以下逻辑......
private Message<?> createReplyMessage(Object reply, MessageHeaders requestHeaders) {
AbstractIntegrationMessageBuilder<?> builder = null;
if (reply instanceof Message<?>) {
if (!this.shouldCopyRequestHeaders()) {
return (Message<?>) reply;
}
builder = this.getMessageBuilderFactory().fromMessage((Message<?>) reply);
}
...
if (this.shouldCopyRequestHeaders()) {
builder.copyHeadersIfAbsent(requestHeaders);
}
return builder.build();
}
So, if you return a Message<?>
your message is returned (enhanced with any inbound headers that you didn't set). 因此,如果您返回
Message<?>
,则会返回您的消息(使用您未设置的任何入站标头进行增强)。
Are you using Spring Integration 3.0.x with Spring Framework 4.0.x? 您是否在Spring Framework 4.0.x中使用Spring Integration 3.0.x? If so, you need to be careful to return an
org.springframework.integration
Message, not an org.springframework.messaging
message. 如果是这样,您需要小心返回
org.springframework.integration
消息,而不是org.springframework.messaging
消息。
If you return an org.springframework.messaging
Message, Spring Integration will indeed wrap it in a Spring Integration Message. 如果你返回一个
org.springframework.messaging
消息,Spring Integration确实会将它包装在Spring Integration Message中。
Core messaging classes were moved to the spring-messaging
module in Spring Framework 4.0, so they can be used for websockets, STOMP etc. 核心消息传递类被移动到Spring Framework 4.0中的
spring-messaging
模块,因此它们可以用于websockets,STOMP等。
Spring Integration 4.0.x now uses those classes as well so you won't see both on the classpath; Spring Integration 4.0.x现在也使用这些类,因此你不会在类路径上看到它们; avoiding the confusion.
避免混淆。 When using Spring Integration 3.0.x with Spring Framework 4.0.x, you need to take great care to use the right classes.
在Spring Framework 3.0.x中使用Spring Integration 3.0.x时,您需要非常谨慎地使用正确的类。
In general, however, we don't recommend adding framework classes (such as Message<?>
) to your code, use POJOs instead, and the framework will take care of the messaging details... 但是,一般情况下,我们不建议在您的代码中添加框架类(例如
Message<?>
),而是使用POJO,框架将处理消息传递细节......
boolean encode(File file) {...}
If you need to access the payload after the encode, consider promoting it to a header beforehand. 如果您需要在编码后访问有效负载,请考虑事先将其提升为标头。
<int:header-enricher ...>
<int:header name="origFile" expression="payload" />
</int:header-enricher>
Then use expression="headers['origFile'].delete()
after the encode. 然后在编码后使用
expression="headers['origFile'].delete()
。
EDIT: 编辑:
Or, return the file (so it becomes the new payload) on success and, on failure, return null
or throw an exception and the downstream flow won't be executed. 或者,在成功时返回文件(因此它成为新的有效负载),并在失败时返回
null
或抛出异常,并且不会执行下游流。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.