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
конфигурации.