Vert.x:阻止处理程序问题

时间:2016-05-17 11:41:27

标签: vert.x

我想使用阻止处理程序,但仍然会收到错误:

java.lang.IllegalStateException: Response has already been written

这是我的代码:

Server.java

r.route("/api/details/send/").handler(BodyHandler.create());
r.route("/api/details/send/").handler(ctx-> {
JsonArray ja = ctx.getBodyAsJsonArray();
JsonArray params = new JsonArray();
vertx.executeBlocking(futur -> {
      for(int i =0; i<ja.size();i++) {
          JsonObject req = new JsonObject();
          req.put("QUERY", "INSERT INTO detailsfacture VALUES ('',?,?,?,?,?,?,?)");
          req.put("DB", "MYSQL_");
          params.add(ja.getJsonObject(i).getValue("typefacture"))
                .add(ja.getJsonObject(i).getValue("activites"))
                .add(Integer.parseInt(ja.getJsonObject(i).getValue("qte").toString()))
                .add(Double.parseDouble(ja.getJsonObject(i).getValue("pu").toString())
                .add(ja.getJsonObject(i).getValue("unite"))
                .add(Double.parseDouble(ja.getJsonObject(i).getValue("montant").toString())
                .add(ja.getJsonObject(i).getValue("codefacture"));
          req.put("PARAMS", params);
          eb.send("EXECUTE", req, res -> {
              if (res.succeeded()) {
                  params.clear();
                  ctx.response().putHeader("content-type", "application/json").end(res.result().body().toString());
              } else {
                  ctx.response().putHeader("content-type", "application/json").end(res.cause().getMessage());
              }

          });

      }
      String result = "orsys";
      futur.complete(result);

  },resultat->{
     ctx.response().putHeader(HttpHeaders.CONTENT_TYPE, "text/plain");
     //resultat.result().toString();
  });
});

MySql.java

eb.consumer("MYSQL_EXECUTE_WITH_PARAMS", req->{
  try{
      JsonObject reqParams = (JsonObject)req.body();
      String sql = reqParams.getString("QUERY");
      client.getConnection( connection -> {
          if (connection.succeeded()) {
              try{
                  SQLConnection con = connection.result();
                  con.updateWithParams(sql,reqParams.getJsonArray("PARAMS"), query -> {
                      if(query.succeeded()){
                          UpdateResult urs = query.result();
                          req.reply(urs.toJson());
                          //req.reply(query.result());
                      }else{
                          req.fail(24, "Err Request : "+query.cause().getMessage());
                      }
                  });
              }catch(Exception e){
                  req.fail(24,  "Err Conn Failed : "+e.getMessage());
              }
          } else {
              req.fail(24,  "Err No Connection : "+connection.cause().getMessage());
          }
      });
  }catch(Exception e){
      req.fail(24, e.getMessage());
  }
});

P.S。 :当我删除executeBlocking时,只有第一个记录在我的数据库中注册。 问候。

2 个答案:

答案 0 :(得分:0)

您在循环中将实体插入detailsfacture。对于每个插入,您可以调用以下内容:

ctx.response().putHeader("content-type", "application/json").end(res.result().body().toString());

如您所见,您调用响应对象的end(...)方法。那是IllegalStateException来自哪里。正如documentation所述:

Once the response has ended, it cannot be used any more.

所以你的问题与executeBlocking无关。

您应该查看HttpServerResponse的{​​{3}}方法。对于每个插页,您应拨打write(...)而不是end(...)。但这只有在您知道整个响应的完整长度时才有效,因为您需要设置标题Content-length。如果您已完成所有插入操作,则需要调用end()来完成响应。此外,您应该只设置一次标题,而不是每次插入。

现在另外一些评论。在您的情况下,我不认为executeBlocking需要。由于Content-length存在问题,我建议使用Future包装每个插页,并使用CompositeFuture组合所有插页。 Future futur的使用方式错误。事件总线的send(...)方法不是阻塞和异步的。因此,在发送所有插入内容后立即调用futur.complete(result)。同样奇怪的是consumer消费MYSQL_EXECUTE_WITH_PARAMSsend发送给EXECUTE

答案 1 :(得分:0)

我尝试了另一种解决方案来获取我的查询(?,?,...,?),(?,?,...,?),..,(?,?,...,? )。

这是我的代码:

public static String getMultipleInsertReq(String table, JsonArray columns,JsonArray data){
JsonObject tab= Tables.Tables_list.getJsonObject(table); // name of table
String sql = "";
if(tab != null){
        sql = "INSERT INTO "+table + "( ";
        if(columns == null){
            columns = tab.getJsonArray("COLS"); //columns from ur database
        }
        if(columns!=null){
            for(int i=0;i<columns.size();i++){
                if(i==columns.size()-1){
                    sql+=columns.getString(i)+") VALUES";
                }
                else{
                    sql+=columns.getString(i)+",";
                }
            }
            for(int i =0; i<data.size();i++){
                for(int j=0; j<columns.size();j++){
                    if(j==columns.size()-1 && i!=data.size()-1){
                        sql+="?),";
                    }
                    else if (i==data.size()-1 && j==columns.size()-1){
                        sql+="?)";
                    }
                    else if (j==0){
                        sql+="(?,";
                    }
                    else{
                        sql+="?,";
                    }
                }
            }
            return sql;
        }
    }
    return  null;
}

希望它有所帮助。 P.S。:它只是一个查询构建器,因此您可以根据需要进行调整。

问候。