8

While trying to test a Vert.x verticle using the event bus through a test class, I'm getting an "blocking errors". Here down the verticle and test classes:

EventBusReceiverVerticle:

public class EventBusReceiverVerticle extends AbstractVerticle {

    public EventBusReceiverVerticle(String name) {
        this.name = name;
    }

    public void start() {

              vertx.eventBus().consumer("geo-service", (Message<JsonObject> handler) -> {
            {
                try {
                    System.out.println("sleep 10 seconds");
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }           
            }
        });
    }
}

The test class:

@RunWith(VertxUnitRunner.class)
public class MyFirstVerticleTest {
    Vertx vertx;
    EventBus eb;
    private static final Logger logger = LoggerFactory.getLogger(MyFirstVerticleTest.class);


    @Before
    public void setUp(TestContext context) {
        logger.info("@Before");
        vertx = Vertx.vertx();
        eb = vertx.eventBus();

        Async async = context.async();
        vertx.deployVerticle(new EventBusReceiverVerticle("R1"), res -> {
            if (res.succeeded()) {
                async.complete();
            } else {
                context.fail();
            }
        });
    }

    @After
    public void tearDown(TestContext context) {
        logger.info("@After");
        Async async = context.async();
        vertx.close(event -> async.complete());
    }


    @Test
    public void testEventBusVerticle(TestContext context) {
        Async async = context.async();
        JsonObject msg = new JsonObject("{\"action\":\"pos\"}");
        eb.send("geo-service", msg, reply -> {
            if (reply.succeeded()) {
                async.complete();
            } else {
                context.fail();
            }
        });
        async.complete();
    }
}

Console output:

Sep 05, 2015 2:20:23 PM com.company.MyFirstVerticleTest
INFO: @Before
sleep 10 seconds
Sep 05, 2015 2:20:24 PM com.company.MyFirstVerticleTest
INFO: @After
Sep 05, 2015 2:20:27 PM io.vertx.core.impl.BlockedThreadChecker
WARNING: Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 2790 ms, time limit is 2000
Sep 05, 2015 2:20:28 PM io.vertx.core.impl.BlockedThreadChecker
WARNING: Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 3794 ms, time limit is 2000
Sep 05, 2015 2:20:29 PM io.vertx.core.impl.BlockedThreadChecker
WARNING: Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 4796 ms, time limit is 2000
Sep 05, 2015 2:20:30 PM io.vertx.core.impl.BlockedThreadChecker
WARNING: Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 5799 ms, time limit is 2000
io.vertx.core.VertxException: Thread blocked
    at java.lang.Thread.sleep(Native Method)
    at com.company.verticals.EventBusReceiverVerticle.lambda$start$1(EventBusReceiverVerticle.java:35)
    at com.company.verticals.EventBusReceiverVerticle$$Lambda$10/2029238960.handle(Unknown Source)
    at io.vertx.core.eventbus.impl.EventBusImpl$HandlerRegistration.handle(EventBusImpl.java:1108)
    at io.vertx.core.eventbus.impl.EventBusImpl.lambda$doReceive$189(EventBusImpl.java:755)
    at io.vertx.core.eventbus.impl.EventBusImpl$$Lambda$17/1888442711.handle(Unknown Source)
    at io.vertx.core.impl.ContextImpl.lambda$wrapTask$15(ContextImpl.java:314)
    at io.vertx.core.impl.ContextImpl$$Lambda$9/911312317.run(Unknown Source)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:357)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
    at java.lang.Thread.run(Thread.java:745)
tmarwen
  • 15,750
  • 5
  • 43
  • 62
rayman
  • 20,786
  • 45
  • 148
  • 246

3 Answers3

10

I had to set the verticle as a worker by setting:

new DeploymentOptions().setWorker(true)
tmarwen
  • 15,750
  • 5
  • 43
  • 62
rayman
  • 20,786
  • 45
  • 148
  • 246
  • just curious what did you use for logging. I was using JUL supplied with vert.x and nothing in my Test class was written out. When I switched to log4j it can't seem to find my log4j.xml file. – Mike Barlotta Sep 23 '15 at 23:01
  • You just need to put on your classpath log4j – rayman Oct 08 '15 at 07:25
  • This is a great answer, but I had to look up where to put it. Use when deploying a verticle as the second parameter: For example `vertx.deployVerticle("com.psi.cassandra.CassandraVerticle", new DeploymentOptions().setWorker(true));` – Jeff Diederiks Jul 29 '18 at 22:02
3

Another option is to increase the timeout

VertxOptions options = new VertxOptions(); 
options.setMaxEventLoopExecuteTime(Long.MAX_VALUE);
vertx = Vertx.vertx(options);`
Xogaz
  • 113
  • 1
  • 9
  • 1
    You shouldn't block the main thread. Setting the timeout to Long.MAX_VALUE can create all sorts of undesirable problems. If you have terrible blocking calls you won't even know. Avoid this solution. – arg20 Aug 14 '17 at 21:02
1

A key sentence in the Vertx documentation is

Don’t block me!

You are getting the blocking message since you do execute blocking code in your Verticle. Calling Thread.sleep(10000) blocks your current verticle for 10 seconds.

Declaring your Verticle as a worker is a workaround. Take a look in the Vertx documentation Executing blocking code. According to the documentation you could tell Vertx to execute Thread.sleep(10000) as blocking code.

vertx.executeBlocking({ future ->
  // Call some blocking API that takes a significant amount of time to return
  Thread.sleep(10000)
  future.complete(result)
}, { res ->
  println("The result is: ${res.result()}")
})

Maybe you can explain the purpose of your test and why you use Thread.sleep(10000)?

saw303
  • 8,051
  • 7
  • 50
  • 90