1
votes

I have a simple websocket connection setup through Play 2.1 that connects to a javascript frontend.

I have a random number generating loop on the server that generates a random number and sends out through the websocket. The random number generation is performed in an unending while loop. I've created an Akka Actor that simply sends a message it receives out through the websocket that was created.

The problem

In the while loop that generates random numbers to be sent through the websocket in each iteration, it never sends anything out through the websocket. When I actually limit the loop so that it actually ends, all the generated numbers are sent at the end of the while loop and does not actually send it in realtime in each iteration. I am not sure how to get this to work so that it sends in each iteration.

See code below.

The Application In Play Framework with the Random Number Generator function

  public class Application extends Controller {


// Default MqTT Messages Actor
static ActorRef defaultMqttActor = Akka.system().actorOf(new Props(WebsocketHandle.class));



public static WebSocket<String> realTimeChartConnection() {
    return new WebSocket<String>() {
        // called when the websocket is established
        public void onReady(WebSocket.In<String> in,
                WebSocket.Out<String> out) {
            // register a callback for processing instream events
            in.onMessage(new Callback<String>() {
                public void invoke(String event) {
                    System.out.println(event);
                }
            });

            System.out.println("Websocket Connection ready ...");

            WebsocketHandle.setWebsocketOut(out);
            sendRandomNumbers();

        }
    };
}

public static void sendRandomNumbers() {

    int prev = 50;
    while (true) {
        int y = (int) (prev + Math.random() * 10 - 5);
        if (y < 0)
            y = 0;
        if (y > 100)
            y = 100;

        defaultMqttActor.tell(""+y);
        System.out.println(""+y);
        try {
            Thread.currentThread();
            Thread.sleep(30);
        } catch (Exception e) {
            System.out.println(e.getStackTrace());
        }
    }
}

}

The WebsocketHandle Actor code

static ActorRef defaultMqttActor = Akka.system().actorOf(new Props(WebsocketHandle.class));

The WebsocketHandle

public class WebsocketHandle extends UntypedActor {

public static WebSocket.Out<String> outStream;

    public static void setWebsocketOut(WebSocket.Out<String> out){
       outStream = out;
    }

    public void onReceive(Object message) throws Exception {

       outStream.write((String)message);

    }

}

As you can see, the actor is simply just sending out the message it receives in 'onReceive'. The random number generation loop is simply 'tell' the number that is generated. I don't understand why it does not send the message asynchronously through the websocket.

Seems like the Websocket is buffering the results ... how can I get the websocket to just send the data immediately?

1
I don't if it is likend to your problem, but beware of these static methods, especially setWebsocketOut in your actor. And please show more code.ndeverge
I've now added the full code. Although it does not tell you anything new ... what I had was just to core functions I'm using but now I'm showing the entire application.java. This is all the code.user2196112

1 Answers

1
votes

I suspect that since you launch an inifinite loop from within the onReady method of the WebSocket response, it's thread is never freed and the messages queue up and are never sent until the loop ends.

What you are looking for is probably a scheduler. It allows to send messages to an actor at regular time intervals or after a delay. Adapted from the official Akka documentation: http://doc.akka.io/docs/akka/snapshot/java/scheduler.html

Akka.system().scheduler().schedule(Duration.create(50, TimeUnit.MILLISECONDS),
  new Runnable() {
    @Override
    public void run() {
      defaultMqttActor.tell("" + Math.random() * 10 + 5, null);
    }
}, system.dispatcher());