Как я могу вернуть значение из метода в Spring Integration и не прерывать исходный поток сообщений?

1

Метод encode компонента fileProcessor отвечает за кодирование видеофайла. Если он сталкивается с проблемой, файл не следует удалять, иначе, если все будет хорошо, его можно удалить. Прямо сейчас единственный способ сохранить поток Message без изменения полезной нагрузки - сделать метод encode void. Мне нужно вернуть некоторую "заголовочную" информацию, хотя SI впоследствии может удалить файл. Я попытался использовать MessageBuilder для создания Message<File> и вернуть его, но когда он поступит в следующий канал, он был завернут, и в Message есть Message, поэтому мое выражение не работает, чтобы вызвать удаление.

Я предполагаю, что могу использовать обернутое Message и выкапывать один уровень в графе объектов, но это кажется неуклюжим.

Каков наилучший подход к привязке к некоторой возвращаемой ценности, не разрушая исходную полезную нагрузку Message и не загрязняя мой метод кодирования POJO каналами SI и отправкой?

Вот моя конфигурация:

<!-- ########################## -->
<!-- ###      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" />

редактировать:

Я использую:

<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:

здесь обновленная конфигурация

<!-- ########################## -->
<!-- ###      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>
Теги:
spring
spring-integration

1 ответ

3
Лучший ответ

Какую версию Spring Integration и Spring Framework вы используете?

Как выглядит подпись fileProcessor.encode()?

Вы не должны получать вложенное 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();
}

Итак, если вы вернете Message<?> Ваше сообщение будет возвращено (усилено с любыми входящими заголовками, которые вы не установили).

Используете Spring Integration 3.0.x с Spring Framework 4.0.x? Если это так, вам нужно быть осторожным, чтобы вернуть сообщение org.springframework.integration, а не сообщение org.springframework.messaging.

Если вы org.springframework.messaging сообщение org.springframework.messaging, Spring Integration действительно будет org.springframework.messaging сообщение интеграции Spring.

Классы основных сообщений были перенесены в модуль Spring spring-messaging в Spring Framework 4.0, поэтому их можно использовать для веб-узлов, STOMP и т.д.

Spring Integration 4.0.x теперь также использует эти классы, поэтому вы не увидите их на пути к классам; избегая путаницы. При использовании Spring Integration 3.0.x с Spring Framework 4.0.x вам нужно проявлять большую осторожность, чтобы использовать нужные классы.

В общем, однако, мы не рекомендуем добавлять в свой код классы инфраструктуры (такие как Message<?>), Вместо этого использовать POJO, и структура будет заботиться о деталях сообщений...

boolean encode(File file) {...}

Если вам нужно получить доступ к полезной нагрузке после кодирования, подумайте о том, чтобы продвигать ее в заголовок заранее.

<int:header-enricher ...>
    <int:header name="origFile" expression="payload" />
</int:header-enricher>

Затем используйте expression="headers['origFile'].delete() после кодирования.

РЕДАКТИРОВАТЬ:

Или верните файл (так что он станет новой полезной нагрузкой) при успешном завершении, а при ошибке возвратите null или выбросите исключение, и поток нисходящего потока не будет выполнен.

  • 0
    Я возвращал сообщение org.springframework.messaging при обнаружении завернутого сообщения. Изменение его на org.springframework.integration привело к желаемому поведению, как вы описываете. Я предпочитаю ваше предложение использовать POJO, и это то, чего я пытался достичь в первую очередь. Я не знал об этом использовании обогащения заголовка (все еще учусь). Теперь это работает, как и ожидалось, большое спасибо за то, что поделились этим решением.
  • 0
    Вот новое сообщение ... 18: 51: 41.373 [task-scheduler-5] DEBUG osichannel.DirectChannel - предварительная отправка по каналу 'encodeDeleteChannel', сообщение: [Payload = true] [Headers = {timestamp = 1401144701371, id = 107b6f6b- c925-deb0-a2a5-7f1dbd2357a8, origFile = C: \ share \ datagator \ encode \ test video.mpg}]

Ещё вопросы

Сообщество Overcoder
Наверх
Меню