How to make a socket server that listens for client connections and opens a socket once an Endpoint is called in Spring? - spring

I have an application that opens a "HttpURLConnection" to a printer. The printer is listening for socket connection and makes a connection when a new TCP socket connection is opened on the Application side (In this case through a new "HttpURLConnection"). Now, I want to mock this printer.
In the Application an Http call is made to the printer server and a socket connection is established between the Application and the server. How do I mock this printer as a spring boot application.

Sounds like you need to take a look into Spring Test Framework and especially its part about a Web: https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/testing.html#spring-mvc-test-client
I would really investigate a possibility to interact via a RestTemplate instead of direct HttpURLConnection and then use that MockRestServiceServer for mocking requests and responses.
Another way is to use a #SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) and implement controller with appropriate mappings and possible return results. This way you would be able to use the mentioned HttpURLConnection to connect to randomly allocated port for HTTP server and perform requests as in production.

Related

set InputBufferSize and Timeout of connection for Netty (Reactive Spring) and heartbeats in Reactive WebSocket?

Maybe somebody has experienced this and can help me out.
I have a Reactive WebSocket server (WebFlux Spring Boot).
I checked the connection to the server by Postman and all is good, the connection lasts a long time, but I don't know how long this connection will last with another clients, so I want to set a couple of parameters: InputBufferSize and Timeout, I found how can do it for some servers (Jetty, TomCat,..):
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#websocket-server-runtime-configuration
But I cannot find how can do it for Netty (I use Reactive WebSocket, based on Netty).
How can set InputBufferSize and Timeout of connection for Netty (Reactive Spring)?
And another question is how to send ping-pong (heartbeats), I think I can do it in MyHandler (that implements org.springframework.web.reactive.socket.WebSocketHandler), in
#Override
public Mono handle(WebSocketSession session)
WebSocketMessage has field type (enum: TEXT, BINARY, PING, PONG) I can use it for ping-pong (heartbeats) between any client and my server part. But many forums write that the Netty has already implemented this process (ping-pong) and it will be superfluous - to add it manually in WebSocketHandler. I'm confused here, should I write additional processing (ping-pong in WebSocketHandler) or it will be an unnecessary layer on top of the already made part in Netty?

How do we connect Spring WebClient to a Unix Domain Socket?

Spring's WebClient underlyingly uses Netty which access to Unix domain sockets. I am trying to make it access /var/run/docker.sock so that I can perform operations using the API as I need /services which is not supported by the docker-java library.
My current workaround is to create a socat container that exposes the Docker socket to TCP within an internal network which in turn allows me to use WebClient's HTTP connections.
Though come to think of it, having this workaround gives one benefit of not needing to put a larger Java application on the manager node.
However, I am still curious how to connect to the unix domain docket.
You can create a Netty HttpClient following their documentation regarding Unix Domain Sockets here.
import io.netty.channel.unix.DomainSocketAddress;
import reactor.netty.http.client.HttpClient;
HttpClient client = HttpClient.create()
.remoteAddress(() -> new DomainSocketAddress("/var/run/docker.sock"));
Then you can tell WebClient to use this HttpClient like this.
WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(client))
.build();
You can expose the docker daemon over TCP and use the REST API.

Share Websocket Session between Spring Micro Service

I've a Spring boot Application for Web sockets. I'm not using Stomp Web socket.
Is there way we can share web socket sessions across multiple instance of micro service.
Is there a way we can save websocket session in Redis or cassandra?
My use case is, i've multiple instance of my micro service is running, which is listening a kafka queue, so when a message received, i need to send it to the client using web socket session.I'm saving the session in the micro service as a MAP. My problem is any one of my micro service is getting the message, if the session is not available with that micro service the message is not going to the client.
If i'm able to save the websocket sesssion in REDIS or Cassandra, i can query the session and sent to the client.
I can't use Stomp web socket as per the requirement, it has to be normal websocket.
You can't. You have to implement some sort of routing from whatever receives the kafka message, to your micro service.
One simple way to do it would be to store in any datastore (mongo, redis, etc) the IP of the service instance for a given client. That way when you get the message from kafka, an you know who is it for, you lookup which machine has the websocket session for that client. Then you call some http endpoint on that IP that you implement to relay a message for a session it's handling.

Jetty websocket client connect to Stomp.js topic channel

I have written a Spring Websocket server which is assessible from a browser via Stomp.js. I am now attempting to implement a Java client in order to connect my server to a secondary system. I am able to connect to the server using the following code
String destUri = "ws://localhost:8080/sample";
WebSocketClient client = new WebSocketClient();
SimpleEchoSocket socket = new SimpleEchoSocket();
try {
client.start();
URI echoUri = new URI(destUri);
ClientUpgradeRequest request = new ClientUpgradeRequest();
client.connect(socket, echoUri, request);
System.out.printf("Connecting to : %s%n", echoUri);
socket.awaitClose(5, TimeUnit.SECONDS);
} catch (Throwable t) {
t.printStackTrace();
}
The connection is opened, and now I would like to connect to my topic /price-stream. This is achieved by stomp.js :
stompClient.subscribe('/topic/pricechannel1', renderPrice);
what is the equivalent subscribe method for my Jetty websocket client? I cant find anything in the documentation I have found on the net.
Additional info:
I am trying to implement the stockticker example found here into another project. I can connect to the server through the provided Stomp.js interface in a web browser. Now I am attempting to create a Java client for use within a Swing GUI using Jetty websocket-client to connect.
I need to connect to the price stream, but it seems I am missing some kind of configuration request to latch on as a destination for the topic
In general, plain websocket clients (as the one provided by Jetty) support the websocket standard. STOMP is a protocol that sits on top of that transport.
Here, you'd need to implement your own STOMP client or interface an existing one with the websocket client you're using.
Spring 4.2 (to be published soon) includes a new STOMP client for this particular use case. See the reference documentation of 4.2.RC2.

A webapp that uses Spring AMQP is that consired to be 1 client?

Hi there i am wondering if i create a webapp that uses Spring AMQP. Is that single webapp 1 AMQP client? Or is every request made by a user that results into an AMQP call a client, so potentially x numbers of clients?
I don't know AMQP much, but I suspect it has the same terminology as jms. In that sense your application is probably pooling connections to AMQP broker for better performance. Each connection in a pool is treated as a separate client (competing consumer).
Thus each request is not really creating a new connection (client), but your application isn't a single client as well. In fact, when your application tries to access AMQP broker, it picks any connection from the pool and puts it back once it's done. Another request can reuse the same connection (client) or use a different, idle one.

Resources