I am currently attempting to perform a Cypher query with my neo4j database as part of an Android Studio application I have made to get started and practise using the REST API. The code for which is shown below:
public class MainActivity extends AppCompatActivity {
private TextView userText;
private Button clicker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userText = (TextView) findViewById(R.id.txtUsername);
clicker = (Button) findViewById(R.id.btnClick);
clicker.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//The REST API needs it's own thread for Neo4j connection. Read up on this documentation.
AsyncTask.execute(new Runnable() {
@Override
public void run() {
try {
//The URL will change based on what is needed for the documentations.
//Provides the address for the HTTP communication.
String neo4jURL = "http://ec2-35-176-79-15.eu-west-2.compute.amazonaws.com:7474/db/data/cypher";
//Helps to create the JSON object used by the query.
//QueryData neo4jqueryData = new QueryData();
//Creates the client used for the connection.
HttpClient neo4jClient = new DefaultHttpClient();
//Assigns the address to either the HttpGet or HttpPost request.
HttpPost neo4jRequest = new HttpPost(neo4jURL);
//Creates the JSON Attributes that will be used as part of the query.
String query = "MATCH (n:Student) WHERE n.Username=\'cs16thm\' RETURN n.StudentID";
JSONObject neo4jJSON = new JSONObject();
neo4jJSON.put("query",query);
neo4jJSON.put("params","");;
String check = neo4jJSON.toString();
Log.d("JSON",check);
StringEntity queryString = new StringEntity(check,"UTF-8");
//Ensures that the application type is JSON.
queryString.setContentType("application/json");
//Adds the Attribute data to the JSON query.
neo4jRequest.setEntity(queryString);
//Adds the Headers to the query.
//bmVvNGo6Z3JvdXAzNw== is the Base64 encoding of the username and password.
neo4jRequest.setHeader("Authorization","Basic bmVvNGo6Z3JvdXAzNw==");
//Shows the data types that would be accepted by the query result.
neo4jRequest.setHeader("Accept", "application/json; charset=UTF-8");
//Used to show the data type being sent to the server.
neo4jRequest.setHeader("Content-Type", "application/json");
Log.d("Check-Type",neo4jRequest.getEntity().toString());
//Performs the neo4j query.
HttpResponse queryResult = neo4jClient.execute(neo4jRequest);
//Checks the status code of the request.
int statusCode = queryResult.getStatusLine().getStatusCode();
if (statusCode == 200 || statusCode == 400){
Log.d("CONNECT","Query Made");
//Gets the results stream from the connection. Results is returned as a JSON which needs to be parsed.
InputStreamReader resultsReader = new InputStreamReader(queryResult.getEntity().getContent());
JsonReader JsonReader = new JsonReader(resultsReader);
//Begins processing of the JSON results.
JsonReader.beginObject();
//Checks all of the parameter keys returned by the document.
Log.d("RESULT","Begin JSON Parse");
while(JsonReader.hasNext()){
//Gathers the name of the current key.
String resultKey = JsonReader.nextName();
//Checks if it's the data we're looking for.
if(resultKey.equals("message")){
//Gathers the String value that we require.
String result = JsonReader.nextString();
//Shows the result in the application.
Log.d("RESULT","Result=" + result);
//Prevents further loop execution now that our data is retrieved.
break;
} else {
//Skips to the next value if the current one contains nothing of interest.
JsonReader.skipValue();
}
}
Log.d("RESULT","End JSON Parse");
//Closes the JSON reader after task to prevent resource hogging.
JsonReader.close();
} else {
Log.d("ERROR", "Request not made " + Integer.toString(statusCode));
}
} catch (MalformedURLException e) {
e.printStackTrace();
Log.d("ERROR", "Bad URL");
} catch (IOException ioe) {
ioe.printStackTrace();
Log.d("ERROR", "Cannot Connect");
} catch (Exception par){
par.printStackTrace();
Log.d("ERROR", "Parse Fail");
}
}
});
}
});
}
}
While my program does successfully receive a response from my neo4j Amazon EC2 server, it replies with an HTTP 400 error and provides the following error messages, present within the output JSON string: Result=Parameters must be a JSON map
, Result=IllegalArgumentException
, Result=java.lang.IllegalArgumentException
Due to these messages, I tried to ensure that my query entity is in the valid JSON format, but despite this, the error message still seems to appear. Despite a significant amount of searching throughout internet sources, I have been unable to find a solution to this problem. I am currently using the Apache HttpClient and Google's Simple JSON external libraries.
I would be grateful if anyone could offer any insight or solutions that would help me solve this problem. I would also be interested in seeing any other Java code that could make my REST API connection. However, I can confirm that many of the official drivers offered by Neo4j, e.g. Neo4j-Java-Driver don't seem to be compatible with Android Studio when trying to connect through the Bolt protocol. Finally, if you have any further questions for me please feel free to ask.
UPDATED:
Omitting the 'params' value as suggested by cybersam does solve the error and produce an HTTP 200 code for a successful query. However when I try to read the JSON file provided by Neo4j as a query result by changing the line if(resultKey.equals("message")) to if(resultKey.equals("data")), I receive the following error message: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY thrown on the line String result = JsonReader.nextString(); along with a ParseException. Neo4j docs say, the JSON file should take a format similar to this: { "columns" : [ "n.StudentID" ], "data" : ["1607174"] }