Spring Integration версии 3.0: разделение потокового сообщения TCP на несколько сообщений в зависимости от содержимого

Я подключаюсь к некому устаревшему сокету сервера, используя интегрированную среду Spring

Ниже моя фабрика клиента и адаптер:

<int-ip:tcp-connection-factory id="client"
                               type="client" 
                               host="${tcpServer}" 
                               port="${tcpPort}" 
                               single-use="false"
                               using-nio="false" />

<int-ip:tcp-inbound-channel-adapter id="inboundServer"
                                    client-mode="true"
                                    channel="inputStream" 
                                    error-channel="errorChannel"
                                    retry-interval="${retryInterval}"
                                    connection-factory="client" />

И ниже преобразователя потока в строку:

    <int:transformer id="clientBytes2String" 
                 input-channel="inputStream"
                 output-channel="inputString" 
                 expression="new String(payload)" />

                 <int:channel id="inputString" />

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


Я попытался с разделителем, он работал, если поток приходит в желаемом формате "ABCD EFGH WXYZ" или "ABCD", но если поток приходит как "ABCD XXXX EFGH WXYZ", то его сбой. Желаемые результаты должны обработать 3 сообщения и 1 ошибку. Но вместо этого обрабатывается 1 сообщение, а все остальные игнорируются.

Код ниже:

 <int:splitter input-channel="inputString"
              output-channel="preRouter2"                  
              method="splitMessage"
              ref="messageSplitterBean"/>

И класс MessageSpliterBean выглядит следующим образом:

@Splitter
public List<Message<?>> splitMessage( Message<?> message ) {

    List<Message<?>> msgFragments = new ArrayList<Message<?>>();

    //Let say I am assuming message will be coming ABCD EFGH WXYZ
    String str[] = message.getPayload().toString().split(" ");
    int counter = 1;
    for ( String s : str ) {

        Message<String> resultMessage = MessageBuilder.withPayload( s )
                .copyHeaders(message.getHeaders())
                .build();
        msgFragments.add(resultMessage);
    }

    return msgFragments;
}

И следующий будет мой маршрутизатор, который будет отправлять на соответствующий канал на основе некоторого выражения:

<int:recipient-list-router id="customRouter" input-channel="preRouter2">
<int:recipient channel="input1" selector-expression="payload.toString().startsWith('ABCD')"/>   
<int:recipient channel="input2" selector-expression="payload.toString().startsWith('EFGH')"/>
<int:recipient channel="input3" selector-expression="payload.toString().startsWith('WXYZ')"/>

Нужен ваш экспертный взгляд на это: о том, что я делаю неправильно, или какой будет наилучший подход.

Вход от сокета сервера будет в потоке данных с фиксированной длиной и пробелом в качестве разделителя. И каждую фиксированную длину мне нужно конвертировать в сообщение и отправлять на соответствующий канал.

С уважением.

1 ответ

Решение

Прежде всего, нет причин для реализации собственного Splitter потому что по умолчанию delimiters опция:

Еще одна моя точка зрения о избыточности <int:transformer> для byte[] -> String, Spring Integration предоставляет вам ObjectToStringTransformer вне коробки.

И ваша проблема <int:recipient-list-router>, Как вы говорите, вы можете иметь что-то не так в ваших данных и ваших router не готов обработать такое сообщение, и оно терпит неудачу для вас. Это только потому, что (AbstractMessageRouter):

else {
    throw new MessageDeliveryException(message, "No channel resolved by router '" + this.getComponentName()
                + "' and no 'defaultOutputChannel' defined.");
}

Что происходит, когда никто selector-expression принимает ваше неправильное сообщение.

В этом случае он отправляется error-channel="errorChannel" на ваше <int-ip:tcp-inbound-channel-adapter> и это останавливает дальнейший процесс только потому, что MessageDeliveryException,

Как вы видите, похоже, чтобы исправить вашу проблему, вы должны добавить default-output-channel к recipient-list-router конфигурации.

Другие вопросы по тегам