У меня есть класс, который расширяет TextWebSocketHandler
, и его основная цель - отправлять сообщения клиенту после определенного события с WebSocketSession
. Чтобы реализовать это, я решил использовать перехват метода, предоставленный Spring AOP.Использование TextWebSocketHandler как @Aspect: после запуска перехватчика WebSocketSession instanse становится null
Проблема, когда перехватчик называется инкапсулированным экземпляром WebSocketSession
становится null
несмотря на то, прежде чем он был экземпляра в методе afterConnectionEstablished()
(который можно увидеть с отладчиком). Интересно, что в каждом другом методе класса можно получить доступ к экземпляру сеанса.
Вот код класса:
@Aspect
public class SystemStateWS extends TextWebSocketHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(SystemStateWS.class);
private WebSocketSession session;
public SystemStateWS() {
}
@Override
public synchronized void afterConnectionEstablished(WebSocketSession session) throws Exception {
this.session = session;
}
@Override
protected synchronized void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println(message.getPayload());
}
@Before("execution(* org.company.MyRestService.processTablesClearQuery(..))")
public void onConfigurationStart(JoinPoint joinPoint) {
if (session.isOpen()) { // session is null here
try {
session.sendMessage(new TextMessage("config started"));
LOGGER.debug("Configuration status message was sent to client");
} catch (IOException e) {
LOGGER.warn("Error during the passing of the message to client");
}
} else {
LOGGER.warn("Unable to send message to client: session is closed");
}
}
@Override
public synchronized void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
LOGGER.debug("Socket is closing");
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
super.handleTransportError(session, exception);
LOGGER.warn("Transport error", exception);
}
}
И файл конфигурации контекста:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<context:component-scan base-package="org.company" />
<aop:aspectj-autoproxy/>
...
<websocket:handlers>
<websocket:mapping path="/ws/sysState" handler="sysStateHandler" />
<websocket:handshake-handler ref="handshakeHandler"/>
</websocket:handlers>
<bean class="org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean">
<property name="maxTextMessageBufferSize" value="335544"/>
<property name="maxBinaryMessageBufferSize" value="335544"/>
</bean>
<bean id="handshakeHandler" class="org.springframework.web.socket.server.support.DefaultHandshakeHandler">
<constructor-arg ref="upgradeStrategy"/>
</bean>
<bean id="upgradeStrategy" class="org.springframework.web.socket.server.standard.TomcatRequestUpgradeStrategy">
</bean>
<bean id="sysStateHandler" class="org.springframework.web.socket.handler.PerConnectionWebSocketHandler">
<constructor-arg type="java.lang.Class" value="org.company.SystemStateWS"/>
</bean>
<bean id="systemStateWS" class="org.company.SystemStateWS"/>
</beans>
MyRestService.processTablesClearQuery
ссылка в @Before
фактически метод в одном из контроллеров REST приложение, но я не думаю, что это имеет большое значение.
К сожалению, я не знаком с такими аспектами. Для начала я даже не знаю, возможно ли комбинировать обработчик сокета с @Aspect
. И если это возможно, в конце концов, почему именно WebSocketSession
становится null
как я могу избежать этого? Любая помощь приветствуется.