Для трехсторонней связи между двумя внешними приложениями, созданными с использованием чего-то другого, и моим приложением Springboot.
Я предполагаю, что TcpInboundGateway, созданный в первом экземпляре, представляет собой запрос-ответ, поэтому он должен ждать ответа, который внешний клиент 2 отправит ему через мое приложение.
В службе, которая получает ответ от TcpOutboundGateway, я Предполагается, что просто установив выходной канал в этой службе с тем же именем, что и ответный канал в tcpInboundGateway, соединение будет установлено. Но это не работает. Так почему же нет заголовка вывода или ответа?
//The inbound gateway
@Bean
public TcpInboundGateway
tcpInboundGateway(AbstractServerConnectionFactory
serverConnectionFactory) {
TcpInboundGateway gateway = new TcpInboundGateway();
gateway.setConnectionFactory(serverConnectionFactory);
gateway.setRequestChannel(requestChannel());
gateway.setLoggingEnabled(true);
gateway.setReplyChannel(backToPos());
gateway.setReplyTimeout(60000);
return gateway;
}
// The outbound gateway
@Bean
@ServiceActivator(inputChannel = "tcpUpslOutgateChannel")
public MessageHandler tcpOutboundGateway() {
TcpOutboundGateway gateway = new TcpOutboundGateway();
gateway.setConnectionFactory(upslClientConnectionFactory());
gateway.setUnsolicitedMessageChannel(unsolicitedChannel());
gateway.setOutputChannelName("forUpslReplyChannel");
return gateway;
}
//Service that handles the response
@ServiceActivator(inputChannel = "forUpslReplyChannel",
outputChannel = "backToPos")
public String
processResponseMessageFromUpslForPurchase(Message<String>
messageFull) {
return processResponseMessageForPurchase(messageFull);
}
Другая конфигурация включает каналы и обработчики сервисов... Ниже приведены логи
024-07-12T08:47:07.307+01:00 INFO 23544 --- [terminal-management] [pool-2-thread-2] c.r.t.s.t.ResponseService : still in the response service
2024-07-12T08:47:07.311+01:00 DEBUG 23544 --- [terminal-management] [pool-2-thread-2] o.s.i.ip.tcp.TcpInboundGateway : failure occurred in gateway sendAndReceive: error occurred in message handler [org.springframework.integration.handler.BridgeHandler@25207619]
2024-07-12T08:47:07.311+01:00 ERROR 23544 --- [terminal-management] [pool-2-thread-2] o.s.i.i.tcp.connection.TcpNetConnection : Exception sending message: GenericMessage [payload=byte[809], headers = {ip_tcp_remotePort=55560, ip_connectionId=127.0.0.1:55560:30002:6a5442c5-0c0d-4217-aab2-fe49776b6d6c, ip_localInetAddress=/127.0.0.1, ip_address=127.0.0.1, id=c841c491-79dc-5e17-4e95-6f7ac6052b79, ip_hostname=127.0.0.1, timestamp=1720770425566}]
org.springframework.messaging.MessageHandlingException: error occurred in message handler [org.springframework.integration.handler.BridgeHandler@25207619]
at org.springframework.integration.support.utils.IntegrationUtils.wrapInHandlingExceptionIfNecessary(IntegrationUtils.java:191) ~[spring-integration-core-6.3.0.jar:6.3.0]
at org.springframework.integration.handler.AbstractMessageHandler.doHandleMessage(AbstractMessageHandler.java:108)
at org.springframework.integration.ip.tcp.connection.TcpNetConnection.run(TcpNetConnection.java:206) ~[spring-integration-ip-6.3.0.jar:6.3.0]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:840) ~[na:na]
Caused by: org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:504) ~[spring-integration-core-6.3.0.jar:6.3.0]
at org.springframework.integration.handler.AbstractMessageProducingHandler.doProduceOutput(AbstractMessageProducingHandler.java:357) ~[spring-integration-core-6.3.0.jar:6.3.0]
at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:286) ~[spring-integration-core-6.3.0.jar:6.3.0]
В вашем клиентском приложении происходит что-то еще. Судя по вашему скриншоту, эта ошибка появилась через 2 секунды. Итак, похоже, что по какой-то причине удалено, например. исключение при отправке. Вы можете включить уровень ведения журнала trace для категории org.springframework.integration.ip.tcp, чтобы наблюдать за активностью клиента в этой категории TcpOutboundGateway.
Итак, я нашел кое-что связанное с переполнением стека. Я решил использовать сотрудничающие адаптеры для получения и ответа на клиент (serviceA) и исходящий шлюз для отправки и получения ответа от сервера (serviceB). Я получаю сообщение об ошибке с исходящим сокетом и соответствующим ответом. Кажется, я не могу реализовать исправление, рекомендованное в этом посте ниже. На самом деле, я еще раз отредактирую вопрос stackoverflow.com/questions/41568806/…
Это слишком много пользовательского кода, который трудно переварить. Почему вы не можете просто использовать TcpInboundGateway и TcpOutboundGateway в Службе B для вызова Службы C? Служба А также может просто использовать TcpOutboundGateway. Таким образом, ответ от Службы C будет таким же TcpInboundGateway. Этот будет ретранслировать ответ обратно на свое соединение до Службы A. Не уверен, зачем вам нужны адаптеры взаимодействующих каналов, поскольку похоже, что это вам не подходит.
@ArtemBilan, надеюсь, у тебя был отличный день. Я воспользовался вашим советом использовать исходящий шлюз и входящий шлюз, но теперь возникла ошибка: нет заголовка вывода или ответа канала. Я чувствую, что я ближе. Я отредактировал вопрос. Пожалуйста, просмотрите его. Ваше здоровье




Шаблон запрос-ответ в Spring Integration реализован через EIP обратного адреса: https://www.enterpriseintegrationpatterns.com/patterns/messaging/ReturnAddress.html.
Итак, когда мы создаем сообщение в нисходящем направлении от входного шлюза, заголовок replyChannel заполняется.
Этот AbstractMessageProducingHandler в вашей трассировке стека может извлечь этот заголовок из сообщения запроса, чтобы правильно доставить ответ на ожидающий сеанс шлюза.
Итак, по сути, нам вообще не нужен gateway.setReplyChannel(backToPos()); на входном шлюзе. У меня даже есть открытая проблема с полным прекращением его поддержки: https://github.com/spring-projects/spring-integration/issues/3985.
Итак, ваш активатор услуги мог бы быть проще:
@ServiceActivator(inputChannel = "forUpslReplyChannel")
Никаких outputChannel вообще. Это оптимизирует не только ваш код, но и поведение во время выполнения, поскольку не будет необходимости в дополнительном мосте между реальным каналом ответа и соответствующим значением заголовка.
Однако оказывается, что сообщение запроса для этого forUpslReplyChannel больше не имеет replyChannel заголовка. Судя по всему, между tcpOutboundGateway и processResponseMessageFromUpslForPurchase у вас есть еще какие-то шаги. Итак, вы создаете новый Message, но теряете заголовки сообщения запроса.
TcpOutboundGateway не делает этого сам по себе, потому что его логика такая:
/**
* Subclasses may override this. True by default.
* @return true if the request headers should be copied.
*/
protected boolean shouldCopyRequestHeaders() {
return true;
}
Я считаю, что уровень ведения журнала отладки для категории org.springframework.integration (или WireTap с подписчиком LoggingHandler) — это хороший способ отслеживать, что происходит с вашим сообщением, когда оно проходит через поток: https://docs.spring.io/spring -integration/reference/channel/configuration.html#channel-wiretap
Спасибо @Артем. Теперь это работает. Пожалуйста, я пытаюсь подключиться к внешнему серверу с помощью SSL. Я думаю, что все сделал правильно, но получаю сообщение «Альтернативное имя ошибки отсутствует». Это ссылка на него, я тоже поделился журналами ошибок stackoverflow.com/questions/78744719/…
Пожалуйста, добавляйте код, а не изображения кода (или журналы): см. Почему бы не загружать изображения ошибок кода, когда задаете вопрос. Отредактируйте вопрос и включите фрагменты кода.