Я работаю над проектом Spring Boot Server, который до сих пор предлагал простые ресурсы REST. Чтобы отправлять уведомления клиенту, я хочу добавить соединение через веб-сокет. Чтобы проверить это соединение, я написал интеграционный тест с использованием клиента SockJS на основе этого руководства:
http://rafaelhz.github.io/testing-websockets/
Проблема в том, что в соединении отказано со следующей ошибкой:
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:9090/websocket/info": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
Моя конфигурация Websocket выглядит следующим образом:
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/websocket")
.setAllowedOrigins("*")
.withSockJS();
}
}
Я вижу, что конечная точка сокета отображается в журнале:
2017-07-14 15:22:59.561 INFO 13765 --- [ main] o.s.w.s.s.s.WebSocketHandlerMapping : Mapped URL path [/websocket/**] onto handler of type [class org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler]
Порт сервера установлен на 9090 в файле application.yml:
server:
port: 9090
Следующий модульный тест не может подключиться к сокету:
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.messaging.WebSocketStompClient;
import org.springframework.web.socket.sockjs.client.SockJsClient;
import org.springframework.web.socket.sockjs.client.WebSocketTransport;
import org.springframework.messaging.simp.stomp.StompFrameHandler;
import org.springframework.messaging.simp.stomp.StompHeaders;
import org.springframework.messaging.simp.stomp.StompSession;
import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
import java.lang.reflect.Type;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import static java.util.Arrays.asList;
import static java.util.concurrent.TimeUnit.SECONDS;
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("test")
//@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class WebSocketConnectionTest {
static final String WEBSOCKET_URI = "ws://localhost:9090/websocket";
static final String WEBSOCKET_TOPIC = "/topic";
BlockingQueue<String> blockingQueue;
WebSocketStompClient stompClient;
@Before
public void setup() {
blockingQueue = new LinkedBlockingDeque<>();
stompClient = new WebSocketStompClient(new SockJsClient(
asList(new WebSocketTransport(new StandardWebSocketClient()))));
System.out.println(WEBSOCKET_URI);
}
@Test
public void shouldReceiveAMessageFromTheServer() throws Exception {
StompSession session = stompClient
.connect(WEBSOCKET_URI, new StompSessionHandlerAdapter() {})
.get(1, SECONDS);
session.subscribe(WEBSOCKET_TOPIC, new DefaultStompFrameHandler());
String message = "MESSAGE TEST";
session.send(WEBSOCKET_TOPIC, message.getBytes());
Assert.assertEquals(message, blockingQueue.poll(1, SECONDS));
}
class DefaultStompFrameHandler implements StompFrameHandler {
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return byte[].class;
}
@Override
public void handleFrame(StompHeaders stompHeaders, Object o) {
blockingQueue.offer(new String((byte[]) o));
}
}
}
В соединении отказано. Я совершенно уверен, что это происходит потому, что конечная точка URI не существует, но я не знаю, почему. Кто-нибудь знает, есть ли ошибка в URI или что-то еще приводит к отказу в соединении?