persisting data of webservice response to forward to websocket - java

I am trying to fetch data through webservice and forward it to the browser through websocketing. So that, I can validate the response of webservice based on the individual websocket opened connection.
Basically, it would be
SERVER1 ---->WEBSERVICE CALL ----> SERVER TO VALIDATE DATA <====> open from client <----WEBSOCKET----> listens to IP through <====>CLIENT
The client is opening a connection to start listening for a particular data for a given MAC address.
I am facing a problem to bypass the data received from webservices to the listener port and IP.
So that, I am trying to persist it using JPA (ODB) objectDB, we could able to store into .odb, but whereas, when trying to make a request to fetch .odb from another application server(CLIENT) to the validator server(SERVER TO VALIDATE DATA). I am getting nothing.
I feel that might be because of lack of session handler among different webapps.
#ServerEndpoint("/echo") //websocket
#Path("/json/metallica") //webservice
public class JSONService {
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_JSON)
public Response createTrackInJSON(Track track) {
// where I am storing into db---------**** step
}
// connection OPENED from differnet **webapp**
#OnMessage
public void echoTextMessage(Session session, String msg, boolean last) {
if (session.isOpen()) {
//I couldn't able to fetch the data from db which I stored in ---------**** step.
}
}
I am getting empty results. Any suggestions where I am going wrong.
Thanks.

Related

Spingboot Websocket Stomp

Could anyone tell me if the server-side implementation is using stomp WebSocket, is the client also expected to implement stomp?
I am trying to implement a spring boot application and I am confused if I should go with or without stomp implementation. From my research, I understand, if you want to scale the application, it is better to use stomp and embedded broker( RabbitMQ for eg.) as it will handle the sessions, heartbeat etc. instead of an in-memory broker.
The examples available online just shows implementations with and without stomp.
I am basically trying to get different datasets from the table upon client request and write to a WebSocket continuously.
Could anyone please confirm if my understanding so far is correct?
What are the essential things I will have to take care of if I go with stomp + websocket?
Updating the usecase below:
The mobile client would be displaying charts upon user login. There would be links in the left panel for eg. Sales, Discounts etc. which upon clicking, the request will reach server through websocket channel. Server will check the datatype in the request, generate the model using data from DB and write the data to the websocket.
Updating code - v1
MyWebSocketHandler:
#Component
public class MyWebSocketHandler extends TextWebSocketHandler {
Logger logger = LoggerFactory.getLogger(getClass());
#Autowired
DashboardUtil dashboardutil;
#Resource(name = "socketSessionsMap")
private Map<String, WebSocketSession> socketSessionsMap;
#Override
public void handleTextMessage(WebSocketSession session, TextMessage message)
throws InterruptedException, IOException {
try {
//Gets the socket session from map and writes a json to that socket - did for testing purpose.
socketSessionsMap.put("session", session);
//String payload = message.getPayload();
String jsonString = dashboardutil.getDataInJSON(); // gets hardcoded json model
session.sendMessage(new TextMessage(jsonString));
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
}
#Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
}
}
WebSecurityConfig:
#Configuration
#EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
#Autowired
private MyWebSocketHandler myWebSocketHandler;
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myWebSocketHandler, "/socketHandler").setAllowedOrigins("*").withSockJS();
}
}
Could anyone tell me if the server-side implementation is using stomp
WebSocket, is the client also expected to implement stomp?
You can register multiple handlers in your web socket configuration. So in theory you can provide a handler for STOMP and another one for plain web socket. If you only provide a STOMP handler then the handshake from a standard web socket client will fail.
From my research, I understand, if you want to scale the application,
it is better to use stomp and embedded broker( RabbitMQ for eg.) as it
will handle the sessions, heartbeat etc. instead of an in-memory
broker.
That's correct. STOMP also offers a few more nice features especially the subscription to certain endpoints.
I am basically trying to get different datasets from the table upon
client request and write to a WebSocket continuously.
That's a really simple description ...
You should think about if you need to share sessions across multiple instances or if you need to send messages between web socket sessions.
From your description it sounds like you just accept a web socket connection and continuously push data to the client. If you want to scale this application you can just put a load balancer in front of your instances and you are good to go.

Identifying seperate websocket requests + spring boot

I am implementing WebSockets for the first time using spring boot. I would like some clarifications on web socket management.
Could I know an efficient way to differentiate separate WebSocket
requests from the client and respond back correctly to the exact
client who made that request? So when a request is received, we will
put that session to a sessionMap in
afterConnectionEstablished() and remove from the map when session is
closed in afterConnectionClosed().
Now, upon getting a request, the service would build a response to
give back to the socket. I would like to know how can I get the key
(map id) to check if that session is available in the sessionMap and
write to the socket if it is available and session.isopen
Should the WebSocket request have a unique ID in the request to
match? So that only upon receiving it back, the client should be
populating the data. Could anyone tell me how it is normally done?

Netty client pipeline getting response in a specific object?

Since all the examples I have seen just output to console in the ClientHandler I'm wondering about a proper way to get this data into a specific object. Let's say in some controller class the user can press a button to request or refresh some data from the server. I have a reference to the channel in this object that sends the request to the server and once the server done the work it sends it back where it ends up in the clients pipeline. Now I need to get the data out and into the object that requested it.
I can think of two options. Implement a observer pattern and send the data back to the object once it's complete and decoded. I'll add the requesting object as a listener once it has send the data and remove it once it received it.
Or perhaps I can just implement a handler interface for this controller class? When it expects data I add it to the pipeline and when it has received the data I remove it from the pipeline? Some pseudo:
public class SomeControllerClass extends ChannelInboundHandlerAdapter {
//...
public void onButtonClick() {
// Send a request to the server.
channel().writeAndFlush(new someDataRequest);
// Add this controller to the pipeline to handle the response once it arrived and decoded.
channel().pipeline().addLast("someHandler", this);
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
// Do stuff with the data in this class
// Remove this from the pipeline.
channel().pipeline().remove("someHandler");
}
//...
}
Is this anywhere along the lines on how I need to approach this problem? I'm removing it from the pipeline because I'm worried other objects that expect similar data will handle the data too.
In other words, all I'm trying to make is a popup window that shows "loading" until data is received from server and ready to present it in that popup.

Spring #ResponseBody can not use session

I have angular2 app and use Tomcat with spring for getting data. I don't want any page reloads or redirects, all I need is data, so all responses from server have #ResponseBody annotations.
My problem is, that because of this annotation I can not get users session variable. When I log in I create session, store user data in it but can not get it with next call.
#JsonIgnoreProperties(ignoreUnknown = true)
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public String login(HttpServletRequest REQ, #RequestBody String BODY) throws Exception
{
...check if all ok...
REQ.getSession().setAttribute("user", user);
... return user data...
}
Is there any other way I can send my data back to client, together with the data needed, to be able to use session.
Edit:
Problem is not on server side but client. Angular is not sending cookie JSESSIONID at cross domain requests by default.
First check your request/response (for example in Chrome dev tools). Tomcat creates new cookie named JSESSIONID to bind client with server session object, so look for this one in your login method response header. Then make sure you are sending this cookie back to your server in next request. Session creation has nothing to do with Spring or #ResponseBody, its lifetime is managed by container (Tomcat).
Also, if you are making cross domain requests, check this answer.
Anything you put on the session context isn't available to clients, it's only available to the server. see this stack overflow post for a good explanation on how servlets work, and specifically the part on how session state works.
As you can see, it works by adding a session-cookie to the response which contains a session-Id. The server stores the session state under that id in memory, and when a future request comes with that session-id, it makes the session state available again to the future request.
If your next requests do not have access to the session state, it's quite possible that the session-cookie isn't propagated properly. I suggest you check that first. It should be in the response where you log in, and should be posted in further requests to the server.

Weird behaviour of tyrus Websocket API

I am developing a websocket server and client which will handle multiple messages.
I am using JSON with decoders and encoders.
As we can have only one #OnMessage method per endpoint, I created one Marker interface called message. Now my #OnMessage method as parameters like void #OnMessage(Message message, Session session) in both Client and Server.
I am sending Register_Send object from #OnConnect of Client using Session.getAsyncRemote().sendObject. Server reads this message successfully and sends Register_Received object to client using Session.getAsyncRemote().sendObject.
Both Register_Send and Register_Received implements Message interface. Both objects are encoded and decoded as JSON objects.
But at client side void #OnMessage(Message message, Session session) method receives Register_Received object as Register_Send. Due to which, exception is thrown.
I am unable to resolve this issue,whether its fault in my code or in Tyrus 1.7 API.
Please suggest me solution for this problem.

Categories