Моя проблема связана с решением, описанным в моей ранее описанной проблеме: Spring integration connecting inbound HTTP gateway with outbound Websocket gateaway. Подводя итог быстро тому, что я пытаюсь сделать, заключается в том, что я хочу передать HTTP-запрос REST, поступающий на мой сервер, другому клиенту websocket, и, получив ответ от клиента websocket, я переношу его в HTTP REST ответ.Весенняя интеграция - Исключение при создании сеанса
Решение, описанное в предыдущей ссылке, работает без проблем. Я попытался немного изменить его, добавив активатор службы lightOnStoringActivator
, который создает сеанс, когда я получаю сообщение на входящем шлюзе websocket (см. Ниже мой новый файл конфигурации). После этой модификации у меня есть исключение, говорящее, что полученное сообщение от клиента weboscket не может быть передано на канал ответа. Я уверен, что проблема возникает из строки, которая создает сеанс, потому что если я удалю только строку, создающую сеанс, проблема исчезнет.
Любая идея, почему это происходит, и как ее исправить?
org.springframework.messaging.MessageHandlingException: ; nested exception is org.springframework.messaging.MessageHandlingException: ; nested exceptionan actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still equestContextListener or RequestContextFilter to expose the current request.
at org.springframework.integration.websocket.inbound.WebSocketInboundChannelAdapter$1.handleMessage(WebSocketInboundChannelAdapter.java:122)
at org.springframework.integration.channel.FixedSubscriberChannel.send(FixedSubscriberChannel.java:70)
at org.springframework.integration.channel.FixedSubscriberChannel.send(FixedSubscriberChannel.java:64)
at org.springframework.integration.websocket.support.PassThruSubProtocolHandler.handleMessageFromClient(PassThruSubProtocolHandler.java:73)
at org.springframework.integration.websocket.inbound.WebSocketInboundChannelAdapter.onMessage(WebSocketInboundChannelAdapter.java:232)
at org.springframework.integration.websocket.IntegrationWebSocketContainer$IntegrationWebSocketHandler.handleMessage(IntegrationWebSocketContain
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75)
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56)
at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:72)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleBinaryMessage(StandardWebSocketHandlerAdapter.java:122)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$100(StandardWebSocketHandlerAdapter.java:42)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$4.onMessage(StandardWebSocketHandlerAdapter.java:88)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$4.onMessage(StandardWebSocketHandlerAdapter.java:85)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageBinary(WsFrameBase.java:549)
at org.apache.tomcat.websocket.WsFrameBase.processDataBinary(WsFrameBase.java:514)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:274)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:116)
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:54)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:192)
at org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:178)
at org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:92)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:601)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.messaging.MessageHandlingException: ; nested exception is java.lang.IllegalStateException: No thread-bound request found:nally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of Disp request.
at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:78)
at org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:71)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:277)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:239)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:95)
at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:164)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:277)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:239)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:95)
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:248)
at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:171)
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutputs(AbstractMessageProducingHandler.java:119)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:277)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:239)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:95)
at org.springframework.integration.endpoint.MessageProducerSupport.sendMessage(MessageProducerSupport.java:101)
at org.springframework.integration.websocket.inbound.WebSocketInboundChannelAdapter.handleMessageAndSend(WebSocketInboundChannelAdapter.java:279
at org.springframework.integration.websocket.inbound.WebSocketInboundChannelAdapter.access$000(WebSocketInboundChannelAdapter.java:63)
at org.springframework.integration.websocket.inbound.WebSocketInboundChannelAdapter$1.handleMessage(WebSocketInboundChannelAdapter.java:119)
... 25 more
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or R
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at com.transacteleurope.service.activator.FingerVeinWebsocketActivator.createHttpSession(FingerVeinWebsocketActivator.java:64)
at com.transacteleurope.service.activator.FingerVeinWebsocketActivator.onEnrollmentCaptureForEnrollResponse(FingerVeinWebsocketActivator.java:15
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:72)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:129)
at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:49)
at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:347)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:87)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:126)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:327)
at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:164)
at org.springframework.integration.util.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:276)
at org.springframework.integration.util.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:142)
at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:75)
... 66 more
Мой конфигурационный файл выглядит следующим образом:
<!-- REST service to turn on the light -->
<int-http:inbound-gateway
supported-methods="POST"
request-channel="lightOnRequest"
reply-channel="lightOnResponse"
path="rest/lighton/{sessionId}">
<int-http:header name="{sessionId}" expression="{sessionId}"/>
</int-http:inbound-gateway>
<!-- We add a header SESSION_ID_HEADER to choose the websocket destination client -->
<int:header-enricher
input-channel="lightOnRequest"
output-channel="lightOnClientRequest">
<int:header
name="#{T(...SimpMessageHeaderAccessor).SESSION_ID_HEADER}"
expression="headers.sessionId"/>
<int:header-channels-to-string/>
</int:header-enricher>
<!-- Websocket out to client -->
<int-websocket:outbound-channel-adapter
channel="lightOnClientRequest"
container="serverWebSocketContainer" />
<!-- Response reception from the Websocket client -->
<int-websocket:inbound-channel-adapter
channel="lightOnClientResponse"
container="serverWebSocketContainer" />
<!-- We store some data in the session -->
<int:service-activator
request-channel="lightOnClientResponse"
reply-channel="lightOnClientStoredResponse"
ref="lightOnStoringActivator"
method="onNewRestfullRequest"
requires-reply="true" />
<!-- The websocket client provides again the reply channel in the headers.
The bridge connects the response to the reply channel -->
<int:bridge input-channel="lightOnClientStoredResponse"/>
Пожалуйста, отправьте полную трассировку стека; возможно, в Gist или подобном, если он слишком велик, чтобы публиковать здесь. –
Я полностью обновил свой первоначальный пост, потому что файл конфигурации XML на самом деле не так, как я сказал. Фактически, я сделал некоторую очистку, чтобы сделать сообщение как можно меньше. Фактически, происходит то, что я пытаюсь создать сеанс после получения ответа от клиента websocket. Но как я могу сказать, что хочу создать сеанс в запросе REST, используя данные, поступающие от клиента websocket? –