My code works perfectly with WS: connection, but it doesn't work when I include my SSL certificate. Let me explain the cenario. When someone sends a message over the internet it reaches my webhook and my webhook sends that message to my websocket. Unfortunately, when I use SSL my java code doesn't work with SSl. The best approach I had was this messa "Unable to create SSLEngine to support SSL/TLS connections" EX2.
EX1 - This code works fine with WS/http
private static WebSocketSessionHandler CLIENTONESESSIONHANDLER = new WebSocketSessionHandler();
public StompSession stompConnection() {
StompSession session = null;
try {
StandardWebSocketClient client = new StandardWebSocketClient();
WebSocketStompClient stompClient = new WebSocketStompClient(client);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
CompletableFuture<StompSession> sessionAsync = stompClient
.connectAsync("ws://localhost:8433/websocket-server", CLIENTONESESSIONHANDLER);
session = sessionAsync.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return session;
}
public void sendMessageToWebSocket(GenericMessageDto obj) {
StompSession session = stompConnection();
session.subscribe("/topic/message", CLIENTONESESSIONHANDLER);
session.send("/app/process-message", obj);
}
public class WebSocketSessionHandler extends StompSessionHandlerAdapter {
@Override
public Type getPayloadType(StompHeaders headers) {
return OutgoingMessage.class;
}
@Override
public void handleFrame(StompHeaders headers, Object payload) {
System.out.println("Received: " + ((OutgoingMessage) payload).getContent());
}
}
EX2
private static WebSocketSessionHandler CLIENTONESESSIONHANDLER = new WebSocketSessionHandler();
public StompSession stompConnection() {
StompSession session = null;
try {
String websocketUrl = "wss://localhost:8443/websocket-server";
StandardWebSocketClient client = new StandardWebSocketClient();
Map<String, Object> userProperties = new HashMap<>();
userProperties.put("org.apache.tomcat.websocket.SSL_CONTEXT", SSLContext.getDefault());
userProperties.put("org.apache.tomcat.websocket.SSL_PROTOCOLS", SSLContext.getDefault());
userProperties.put("org.apache.tomcat.websocket.SSL_TRUSTSTORE", SSLContext.getDefault());
client.setUserProperties(userProperties);
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
SSLContext sslContext = SSLContext.getDefault();
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
WebSocketStompClient stompClient = new WebSocketStompClient(client);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
session = stompClient.connectAsync(websocketUrl, CLIENTONESESSIONHANDLER, sslSocketFactory, container, sslContext).get();
} catch (Exception e) {
e.printStackTrace();
}
return session;
}
public void sendMessageToWebSocket(GenericMessageDto dto) {
StompSession session = stompConnection();
session.subscribe("/topic/message", CLIENTONESESSIONHANDLER);
session.send("/app/process-message", dto);
}
I've found a solution. Fisrt of all you need to add the trust store file and key store file. Have a look here: https://www.baeldung.com/spring-boot-https-self-signed-certificate
Load the keystore using a special class Keystore as exampl below. When using SSl we need to get the instace: SSLContext sslContext = SSLContext.getInstance("TLS");
Just remember to change this ""wss://:5000/websocket-server" for your website url. It is not going to work if you write down "localhost" nor your IP address because SSL. I wrote a method as a connection and returning a session and then I do the subcribe like this:
public void updateWebsocket() {
StompSession session = stompConnectionTLS();
session.subscribe("/topic/messages", CLIENT_SESSION_HANDLER);
session.send("/app/process", true);
session.disconnect();
}
public StompSession stompConnectionTLS() {
StompSession session = null;
String websocketUrl = "wss://<yourURL>:5000/websocket-server";
try {
String trustStoreFile = "/Path/cert.jks";
String trustStorePassword = "Password";
String keyStoreFile = "/Path/keystore.p12";
String keyStorePassword = "Password";
// Load the trust store
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(new FileInputStream(trustStoreFile), trustStorePassword.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
// Load the key store
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream(keyStoreFile), keyStorePassword.toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
StandardWebSocketClient webSocketClient = new StandardWebSocketClient();
webSocketClient.setUserProperties(Collections.singletonMap("org.apache.tomcat.websocket.SSL_CONTEXT", sslContext));
WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
session = stompClient.connectAsync(websocketUrl, CLIENTSESSIONHANDLER).get();
} catch (Exception e) {
e.printStackTrace();
}
return session;
}