Weird behaviour of tyrus Websocket API - java

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.

Related

How can I return response from RabbitMQ producer to RestController?

I have got two Spring Boot application. First one is REST application. The REST one is communicating with second application through RabbitMQ message queue. I'm sending a request to method with the #GetMapping("/") and this method producing a message to example-queue. A method with #RabbitListener(queues = {"example-queue"}) taking the message and create a object at database. Now, how can I send my response (saved object) to the method with #GetMapping("/")? I need a response from consumer to ResponseEntity.ok();. How can I do that? Thank you.
Just see if you can make the interaction with RabbitMQ consumer as a request-reply pattern.
The #RabbitListener can just return your object and be marked with a #SendTo. This way the framework will look into a replyTo property of the request message.
On the producer side you can just use an AmqpTemplate.convertSendAndReceive().
See more in docs: https://docs.spring.io/spring-amqp/docs/current/reference/html/#request-reply

STOMP Websocket synchronous communication using Spring

I have a requirement were some of the STOMP websocket connections needs to be handled synchronously.
Meaning I have a client (spring) subscribed to a topic ("/topic").
I have a server (spring) that has defined the broker ("/topic") also defined handlers ("/app/hello").
Now is it possible for the client to send a request to /app/hello and then wait for a response before sending the next request to /app/hello.
How do I return value on my sever (STOMP spec says about RECEIPT frames but I don't think this is something that can be manually controlled).
How do I wait for the value on my client after a send.
To connect a Java client to a websocket endpoint you can use the tyrus reference implementation of JSR356 - Websockets For Java.
Basically you will need to implement a client endpoint (javax.websocket.Endpoint) and a message handler (javax.websocket.MessageHandler). In the endpoint you register the message handler with the current session on open:
public class ClientEndpoint extends Endpoint {
...
#Override
public void onOpen(final Session aSession, final EndpointConfig aConfig) {
aSession.addMessageHandler(yourMessageHandler);
}
}
To connect to the server endpoint you can use the ClientManager:
final ClientManager clientManager = ClientManager.createClient();
clientManager.connectToServer(clientEndpoint, config, uriToServerEndpoint);
The message handler's onMessage method will be invoked, if the server endpoint sends something to the topic.
Depending on your needs you can either choose to implement the mentioned interfaces or use the corresponding annotations.
UPDATE:
The STOMP website lists several implementations of the STOMP protocol. For Java there are Gozirra and Stampy. I have no experience with these frameworks but the examples are pretty straight forward.

persisting data of webservice response to forward to websocket

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.

Session Identification in Tyrus WebSocket API

I have implemented a websocket server which acts as observer for some events.
#ServerEndPoint
public class Server implements SomeObserver
I have implemented objectChanged() from SomeObserver class. The objectChanged() will execute when there is some event will be occur. It is common observer implemnetation.
The application logic is like this:
Clients connect to Websocket server and server sends appropriate events for appropriate clients.
I have coded it like this:
#ServerEndPoint
public class Server implements SomeObserver
{
Session clientSession = null;
#OnOpen
public void OnOpen(Session session}
{
clientSession = session;
}
//implemented OnMessage and OnClose, OnError methods
public void objectChanged(Event[] event)
{
clientSession.sendAsyncRemote().sendObject(someObjectInfo);
}
I never used any session identification. But surprisingly, server sends appropriate messages for respective session. Server does not send one sessions event to another session without any session authentication or identification.
Does anyone know why and how it happens in Tyrus API.
I want to know how Tyrus webocket support session identification.
clientSession.sendAsyncRemote().sendObject(someObjectInfo);
In the above line, the session object will be created per connection basis. It holds the reference socket object (per connection).
Hence, when message is sent, data will be transferred to the respective client.

Java Spring Web Service Client Fault Handling

I have written a web service client (using Java Spring and JAXB Marshaller) that works with the UPS web service. When I send a valid request everything works well. When I send an invalid request (weight > 150 lbs) then the UPS web service responds with a SOAP Fault. The client application just fails with a
org.springframework.oxm.UnmarshallingFailureException: JAXB unmarshalling
exception; nested exception is javax.xml.bind.UnmarshalException:
unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Fault").
Obviously my program isn't able to decipher the SOAP fault returned by the web service. I wrote a custom FaultMessageResolver, but it doesn't get invoked. Here's the code:
public class UpsRateClient extends WebServiceGatewaySupport {
public UpsRateClient(WebServiceMessageFactory messageFactory) {
super(messageFactory);
getWebServiceTemplate().setFaultMessageResolver(new UpsFaultMessageResolver());
}
public RateResponse getRate(RateRequest rateRequest) {
return (RateResponse) getWebServiceTemplate().marshalSendAndReceive(rateRequest, new UpsRequestWSMC());
}
private class UpsFaultMessageResolver implements FaultMessageResolver {
public void resolveFault(WebServiceMessage message) throws IOException{
System.out.println("Inside UpsFaultMessageResolver");
}
}
}
Thanks for your time!
I had the same problem (SOAP error with HTTP 200OK) and I solved it setting the CheckConnectionForFault property to false. See.
Take a wireshark trace.My thought is that perhaps the web service sends the SOAP fault using (erroneously) a HTTP 200OK instead of a 500 Internal Server error and your client tries to handle it as a valid response.
If this is the case this is then the problem lies in the web service which does not addere to SOAP standard(my emphasis):
From SOAP RFC
In case of a SOAP error while processing the request, the SOAP HTTP
server MUST issue an HTTP 500 "Internal Server Error" response and
include a SOAP message in the response containing a SOAP Fault element
(see section 4.4) indicating the SOAP processing error.
If you do not own the web service, they should fix this.
To be honest I am not sure what the work arround would be in Spring-WS.
If I really needed a work arround in Jax-Ws I would replace the stub call with a Dispatcher to handle the raw xml myself and avoid the automatic marshal/demarhal.
Look into Spring-Ws if you can do the same, but this is a bug of the web service, not your client

Categories