keenlabs / KeenClient-Java

Official Java client for the Keen IO API. Build analytics features directly into your Java apps.
https://keen.io/docs
MIT License
74 stars 43 forks source link

unable to send events with Java sdk (error is: "The specified JSON is invalid. No JSON object could be decoded") #64

Closed pgoldweic closed 9 years ago

pgoldweic commented 9 years ago

(UPDATED POST)

I originally posted here on 9/30 regarding a problem sending events to Keen using the Java SDK, in which I was experiencing the following error logs (note: the SDK error message does not make sense, since the Json in question is valid)

FINER: Adding event to collection: SillyCollection Sep 30, 2015 1:42:03 PM io.keen.client.java.KeenLogging log FINER: Sent request '{"keen":{"timestamp":"2015-08-05T21:34:12.290Z"},"name":"Silly Name","id":123,"user":{"role":"user","id":9111,"class_role":"student"}}' to URL 'https://api.keen.io/3.0/projects/55ef2fa159949a355159a02c/events/SillyCollection' Sep 30, 2015 1:42:03 PM io.keen.client.java.KeenLogging log FINER: Received response: '{"message": "The specified JSON is invalid. No JSON object could be decoded", "error_code": "InvalidJSONError"}' (400)

After further experimentation, turns out that Keen does not return an error when the default json serializer/deserializer (that is, jackson) is used instead of my choice (flexjson). Interestingly enough, the json produced by the default, and my replacement one, seem to be exactly the same -according to the Keen logger. This suggests that there may be a problem on your end that causes the json to be rejected as invalid.

Here's the output when I use Jackson:

FINER: Sent request '{"keen":{"timestamp":"2015-08-05T21:34:12.290Z"},"name":"Silly Name","id":123,"user":{"role":"user","id":9111,"class_role":"student"}}' to URL 'https://api.keen.io/3.0/projects/55ef2fa159949a355159a02c/events/SillyCollection' Oct 05, 2015 1:58:22 PM io.keen.client.java.KeenLogging log FINER: Received response: '{"created": true}' (201)

And here's the output when I use MyKeenJsonHandler (which I include below) instead:

FINER: Sent request '{"keen":{"timestamp":"2015-08-05T21:34:12.290Z"},"name":"Silly Name","id":123,"user":{"role":"user","id":9111,"class_role":"student"}}' to URL 'https://api.keen.io/3.0/projects/55ef2fa159949a355159a02c/events/SillyCollection' Oct 05, 2015 2:03:02 PM io.keen.client.java.KeenLogging log FINER: Received response: '{"message": "The specified JSON is invalid. No JSON object could be decoded", "error_code": "InvalidJSONError"}' (400) Oct 05, 2015 2:03:02 PM io.keen.client.java.KeenLogging log FINER: Encountered error: {"message": "The specified JSON is invalid. No JSON object could be decoded", "error_code": "InvalidJSONError"}

Here's my json handler code for your inspection: File: MyKeenJsonHandler.java (defines a Json handler that uses flexjson)

package edu.northwestern.at.yellowdig.process.test; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.util.Map;

import flexjson.JSONDeserializer; import flexjson.JSONSerializer; import io.keen.client.java.KeenJsonHandler;

public class MyKeenJsonHandler implements KeenJsonHandler {

@Override
public Map<String, Object> readJson(Reader arg0) throws IOException {
    Map<String, Object> result = new JSONDeserializer<Map<String, Object>>().deserialize(arg0);
    return result;
}

@Override
public void writeJson(Writer arg0, Map<String, ?> arg1) throws IOException {
    new JSONSerializer().exclude("*.class").deepSerialize(arg1, arg0);
}

}

Geeber commented 9 years ago

Hi Patricia, sorry again for the wait. I have now reproduced this error locally and am working on debugging it. I'll update this ticket as I make progress.

Geeber commented 9 years ago

Ah, I believe I found the problem. The writeJson method requires that you close the Writer once you're done. Jackson does this automatically inside the writeValue call, which is why it works. This should be better documented - I'll make a note to update the Javadocs for writeJson.

Can you please try adding arg0.close(); to your writeJson implementation after the line you already have there, and let me know if that fixes it for you?

pgoldweic commented 9 years ago

Hi there! Glad that you were able to reproduce and easily debug the problem. Yes, I just confirmed that adding the "arg0.close();" call to the writeJson method fixes the problem. Many thanks!

Geeber commented 9 years ago

No problem! Sorry again that it took so long to get back to you. And I'll make sure to update the Javadoc in the next release.