vert-x / mod-mysql-postgresql

Vert.x 2.x is deprecated - use instead
http://vertx.io/docs/vertx-mysql-postgresql-client/java/
Apache License 2.0
49 stars 17 forks source link

java.lang.String cannot be cast to org.vertx.java.core.json.JsonArray #62

Closed RowanKaag closed 9 years ago

RowanKaag commented 9 years ago

might be related to #22 .

In my vert.x application, routematching:

JsonObject eventBusData = new JsonObject();
request.bodyHandler((Buffer buffer) -> {
JsonObject body = new JsonObject(buffer.toString());
eventBusData.putObject("body", body);
sendToController(controller, eventBusData, request);
}
public void sendToController(String controller, JsonObject eventBusData, HttpServerRequest request) {
        EventBus eb = vertx.eventBus();
        eb.send(controller, eventBusData, (Message<JsonObject> message) -> {
            request.response().end(message.body().toString());
        });
    }

in the corresponding controller:

eb.registerHandler("articles.insert", (Message<JsonObject> message) -> {
            JsonObject body = message.body().getValue("body");
            JsonArray fields = new JsonArray();
            JsonArray values = new JsonArray();
            for (String key : body.getFieldNames()) {
                fields.addString(key);
                values.add(body.getValue(key));
            }
                eb.send("mysql",
                    new JsonObject()
                        .putString("action", "insert")
                        .putString("table", "articles")
                        .putArray("fields", fields)
                        .putArray("values", values)
                    , (Message<JsonObject> data) ->
                            message.reply(data.body())
                    );

request body:

{
    "name": "pannekoek",
    "age": 150,
    "archived": true
}

response:

Uncaught Exception for request {"action":"insert","table":"articles","fields":["name","age","archived"],"values":["pannekoek","150","true"]}
java.lang.ClassCastException: java.lang.String cannot be cast to org.vertx.java.core.json.JsonArray
Narigo commented 9 years ago

Could you add some more information where this exception occurs? Does it still occur, if you don't add the fields / values in that for-loop? Could you try to add some debug statements and see if some strange casting happens?

RowanKaag commented 9 years ago

this works, but it's rather static:

                eb.send("mysql",
                    new JsonObject()
                        .putString("action", "insert")
                        .putString("table", "articles")
                        .putArray("fields", new JsonArray().addString("name").addString("age"))
                        .putArray("values", new JsonArray().addArray(new JsonArray()
                            .addString(message.body().getObject("body").getString("name"))
                            .addNumber(message.body().getObject("body").getNumber("age")))), (Message<JsonObject> data) ->
                        message.reply(data.body())
                );

this doesn't:

            JsonArray fields = new JsonArray();
            JsonArray values = new JsonArray();
            for (String key : body.getFieldNames()) {
                fields.addString(key);
                values.addArray(body.getValue(key));
            }
                eb.send("mysql",
                    new JsonObject()
                        .putString("action", "insert")
                        .putString("table", "articles")
                        .putArray("fields", fields)
                        .putArray("values", values)
                    , (Message<JsonObject> data) ->
                            message.reply(data.body())
                    );

omitting:

.putArray("fields", fields)

still gives

java.lang.String cannot be cast to org.vertx.java.core.json.JsonArray

omitting:

.putArray("values", values)

gives a nullpointerexception

Narigo commented 9 years ago

This sounds more like a vert.x issue for me regarding the JSON API. Could you ask on the list? Maybe someone has a better workaround than the static code you pasted.. Am 19.01.2015 17:00 schrieb "Rowan Kaag" notifications@github.com:

this works, but it's rather static:

            eb.send("mysql",
                new JsonObject()
                    .putString("action", "insert")
                    .putString("table", "articles")
                    .putArray("fields", new JsonArray().addString("name").addString("age"))
                    .putArray("values", new JsonArray().addArray(new JsonArray()
                        .addString(message.body().getObject("body").getString("name"))
                        .addNumber(message.body().getObject("body").getNumber("age")))), (Message<JsonObject> data) ->
                    message.reply(data.body())
            );

this doesn't:

        JsonArray fields = new JsonArray();
        JsonArray values = new JsonArray();
        for (String key : body.getFieldNames()) {
            fields.addString(key);
            values.addArray(body.getValue(key));
        }

            eb.send("mysql",
                new JsonObject()
                    .putString("action", "insert")
                    .putString("table", "articles")
                    .putArray("fields", fields)
                    .putArray("values", values)
                , (Message<JsonObject> data) ->
                        message.reply(data.body())
                );

— Reply to this email directly or view it on GitHub https://github.com/vert-x/mod-mysql-postgresql/issues/62#issuecomment-70516785 .

RowanKaag commented 9 years ago

https://groups.google.com/forum/#!topic/vertx/oULydwexKGI, will be posting a solution if the post gets any.

RowanKaag commented 9 years ago

this seemed to do the trick:

values.addArray(new JsonArray().add(body.getValue(key)));

however I now get a MySQL error:

Error 1136 - #21S01 - Column count doesn't match value count at row 1

println of query:

fields: ["name","age","archived"]

values: [["pannekoek"],[150],[0]]

query: {"action":"insert","table":"articles","fields":["name","age","archived"],"values":[["pannekoek"],[150],[0]]}

database layout:

mysql> DESCRIBE articles;
+----------+---------------------+------+-----+---------+----------------+
| Field    | Type                | Null | Key | Default | Extra          |
+----------+---------------------+------+-----+---------+----------------+
| id       | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name     | text                | YES  |     | NULL    |                |
| age      | int(11)             | YES  |     | NULL    |                |
| archived | tinyint(4)          | YES  |     | NULL    |                |
+----------+---------------------+------+-----+---------+----------------+
4 rows in set (0,01 sec)
Narigo commented 9 years ago

Argh, still wrong, sorry. values wants a list of rows. So you need to send this here:

{
  "action" : "insert",
  "table" : "articles",
  "fields" : ["name", "age", "archived"],
  "values" : [
    ["pannekoek", 150, 0]
  ]
}

So in your case, I think it should be this code...?

eb.registerHandler("articles.insert", (Message<JsonObject> message) -> {
  JsonObject body = message.body().getValue("body");
  JsonArray fields = new JsonArray();
  JsonArray rowValues = new JsonArray();
  for (String key : body.getFieldNames()) {
    fields.addString(key);
    rowValues.add(body.getValue(key));
  }
  eb.send("mysql",
    new JsonObject()
      .putString("action", "insert")
      .putString("table", "articles")
      .putArray("fields", fields)
      .putArray("values", new JsonArray().addArray(rowValues)),
    (Message<JsonObject> data) -> message.reply(data.body()));
RowanKaag commented 9 years ago

oh my, it worked. thank you!