Recently, I want to choose an efficient, simple and extensible Web box as the background of mobile platform. After comparing a series of frames, I chose VerTX. But after a period of use, found some problems with VerTX.

1. Duplicate code generated by vertx using shared resources

In VertX, Verticle is the most basic structure, simply speaking, similar to J2EE servlet, but Verticle is more flexible, not only can be a service, but also can be a client, verticle communication through EventBus, actually more similar to Akka actor. Vertx implements a Web framework similar to NodeJS Express style, but Java is multithreaded, and typically Java’s target environment is more complex. This creates a series of problems. For JDBC connection pools, a similar statement must be introduced in Verticle’s start at creation time

JDBCClient client = JDBCClient.createShared(vertx, new JsonObject().clear() .put("provider_class", "io.vertx.ext.jdbc.spi.impl.HikariCPDataSourceProvider") .put("jdbcUrl", "JDBC: postgresql: / / 127.0.0.1:5432 / mydb"), put (" username ", "postgres") .put("password","password") .put("driverClassName", "org.postgresql.Driver") .put("maximumPoolSize", 30),"mypool");Copy the code

If there is another Verticle that needs to use the connection pool mypool, such a paragraph must also be added to the start method. Verticle is deployed in an asynchronous multithreaded environment, and the createShared method must be thread-safe. If there are many programs that need to use the connection pool Mypool, there will be a lot of redundant code that must be thread-safe. One possible solution is to create a Configuration Verticle that initializes all shared resources. All shared resources of the system are then accessed through this static method of Verticle. This reduces a lot of redundant code and, as a singleton class, does not have to be thread-safe.

Note that when deploying Verticle with vertx.deployverticle (vertx is understood to be a Verticle environment), there is no guarantee of verticle run order and deployment is asynchronous. To ensure that configuration Verticle runs before other Verticle, the deployment process must be synchronized. The synchronous method is not complicated and can be implemented with a Future.

try { log.info("deploy " + verticleID); CompletableFuture future = new CompletableFuture(); vertx.deployVerticle(verticleID, deploymentOptions, res -> { if (res.succeeded()) { log.info("Deployment id is: " + res.result()); future.complete(1); } else { log.error("Deployment failed!" ); future.complete(0); }}); int result = future.get(); } catch (Throwable t) { log.error("error", t); }Copy the code

2. Asynchronous JDBC

Asynchronous JDBC does improve efficiency. Vertx provides an asynchronous API based on SQL statements. Here is an example from verTX JDBC example.

// create a test table execute(conn.result(), "create table test(id int primary key, name varchar(255))", create -> { // start a transaction startTx(conn.result(), beginTrans -> { // insert some test data execute(conn.result(), "insert into test values(1, 'Hello')", insert -> { // commit data endTx(conn.result(), commitTrans -> { // query some data query(conn.result(), "select count(*) from test", rs -> { for (JsonArray line : rs.getResults()) { System.out.println(line.encode()); } // and close the connection conn.result().close(done -> { if (done.failed()) { throw new RuntimeException(done.cause()); }}); }); }); }); }); }); }); }Copy the code

This is such a simple transaction that it is impossible to imagine what a complex transaction handler would look like. The JDBC Driver API is still synchronous, but VerTX provides an asynchronous wrapper. The statement-level asynchronous API is too fine-grained, a situation that would be ameliorated if programmers could control the granularity of asynchrony themselves. My solution is to provide a JDBC synchronization API, and then a programmer can encapsulate a procedure asynchronously. This is easy to implement in VerTX.

executor.executeBlocking((Future f) -> {
      try {
          jdbc_routine();
        }
        f.complete();
      } catch (SQLException e) {
        f.fail(e);
      }
    }, handler);
Copy the code

Vertx’s architecture is certainly very advanced, with multi-threaded asynchronous architecture, built-in metrics, support for clusters, and high availability, which nodeJS can’t easily provide. But the current use does have a lot of constant, need a bit of hack.