1

I'm writing a ClientConnector class using NetClient and JsonParser.

Here are the steps I went into:

  1. Connect to server using NetClient
  2. Use Pump to handle backpressure
  3. Use io.vertx.core.parsetools.JsonParser to parse full JSON response objects
  4. Write 2 requests on socket

The problem is that I get a server response only for the 1st request.

How can I get responses for subsequent requests?

Here down the AsyncClientConnector class code:

package com.luckyrhinos.sbg.robots;

import static io.vertx.core.parsetools.JsonEventType.VALUE;
import static org.awaitility.Awaitility.await;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import org.junit.Test;

import com.luckyrhinos.core.common.utils.RefHolder;

import io.vertx.reactivex.core.Vertx;
import io.vertx.reactivex.core.net.NetClient;
import io.vertx.reactivex.core.net.NetSocket;
import io.vertx.reactivex.core.parsetools.JsonParser;
import io.vertx.reactivex.core.streams.Pump;

public class JsonRequestTest {

  @Test
  public void testName() throws Exception {

    Vertx vertx = Vertx.vertx();

    NetClient client = vertx.createNetClient();

    RefHolder<NetSocket> hSocket = new RefHolder<>();

    AtomicBoolean ready = new AtomicBoolean(false);
    client.rxConnect(12344, "localhost") //
        .subscribe(socket -> {
          Pump.pump(socket, socket).start();
          JsonParser parser = JsonParser.newParser().objectValueMode();
          hSocket.obj = socket;

          socket //
              .exceptionHandler(e -> {
                e.printStackTrace();
                client.close();
              }) //
              .endHandler(v -> {
                System.out.println("Done!");
                client.close();
              }) //
              .handler(parser::handle);

          parser.handler(event -> {
            if (event.type() == VALUE) {
              System.out.println(event.value());
            }
          });

          ready.set(true);
        });

    await().atMost(5, TimeUnit.SECONDS).untilTrue(ready);

    ready.set(false);
    hSocket.obj.write("{ \"type\":\"SetupRequest\",\"ply\":2 }");
    hSocket.obj.write("{ \"type\":\"PingRequest\", \"id\":\"123456789\" }");

    await().atMost(5, TimeUnit.SECONDS).untilTrue(ready);
  }
}
tmarwen
  • 15,750
  • 5
  • 43
  • 62
Shvalb
  • 1,835
  • 2
  • 30
  • 60

1 Answers1

0

You have three issues:

  • Pump.pump(socket, socket).start(); does not do what you think it does. Maybe try deleting that. Don't "handle backpressure."
  • Do not use a RefHolder. Just use a 1-length array here.
  • Wrap your obj.write in a vertx.runOnContext call. You shouldn't use vertx objects outside of a vertx context. Or, examine the Vertx JUnit Test Runner and see if it meets your needs (this will give you a TestContext parameter for your test).

Without your server code, it's hard to tell if your server will correctly handle the two messages without a prefixed length argument (i.e., if you have a correctly-implemented equivalent of JsonParser).

You almost certainly want to use something like web sockets if you prefer a message model instead of a stream model. TCP is unsuitable, by itself without something like length prefixing, for the task you're suggesting you're using it for

DoctorPangloss
  • 2,994
  • 1
  • 18
  • 22