I have a simple app communicating with its Servlet backend through an Async task. I have some trouble understanding how the messages are wrapped up and how to manipulate the data structures of these messages. What I want to do is to receive either multiple objects, or multiple heterogeneous information anyway. My code:
public class MyServlet extends HttpServlet {
ArrayList<Tour> m_tours;
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/plain");
resp.getWriter().println("Please use the form to POST to this url");
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String order = req.getParameter("order");
resp.setContentType("text/plain");
if (order == null) {
resp.getWriter().println("Please enter a name");
}
resp.getWriter().println("yay name received");
ArrayList<Tour> m_tours = getTours(); //returns a populated ArrayList of custom Tour objects
resp.getWriter().print(m_tours);
}
private void getTours(){
//some code here
}
}`
And my Async task class:
class ServletPostAsyncTask extends AsyncTask<Pair<Context, String>, Void, String> {
private Context context;
@Override
protected String doInBackground(Pair<Context, String>... params) {
context = params[0].first;
String order = params[0].second;
String[] url = new String[3];
url[0] = "http://192.168.169.85:8080/hello";
url[1] = "http://10.0.2.2:8080/hello";
url[2] = "http://192.168.1.102:8080/hello";
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url[2]);
List<NameValuePair> nameValuePairs = new ArrayList<>(1);
nameValuePairs.add(new BasicNameValuePair("order", order));
try {
// Add name data to request
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
if (response.getStatusLine().getStatusCode() == 200) {
return EntityUtils.toString(entity);
}
return "Error: " + response
.getStatusLine()
.getStatusCode() + " " + response
.getStatusLine().getReasonPhrase();
} catch (ClientProtocolException e) {
return e.getMessage();
} catch (IOException e) {
return e.getMessage();
}
}
@Override
protected void onPostExecute(String result) {
String result1 = "Response: "+result;
Toast.makeText(context, result1, Toast.LENGTH_LONG).show();
}
}
The response message returns ArrayList as text:
Response: yay name received
packagename@objectkey1
packagename@objectkey2
packagename@objectkey3
...
packagename@objectkeyn
But instead, what I want is to store it as it is, as an ArrayList. How can I configure my Async task to receive my m_tours ArrayList and store it somewhere for further use? Furthermore, how can I configure it to receive multiple objects?
* EDIT *
I've tried by using Gson as suggested by @orip, setting the Async task as follows:
@Override
protected String doInBackground(Pair<Context, String>... params) {
context = params[0].first;
String order = params[0].second;
String[] url = new String[3];
url[0] = "http://192.168.169.85:8080/hello";
url[1] = "http://10.0.2.2:8080/hello";
url[2] = "http://192.168.1.102:8080/hello";
// HttpPost httpPost = new HttpPost("http://semiotic-art-88319.appspot.com/hello");
HttpClient httpClient = new DefaultHttpClient(); //127.0.0.1 - 10.201.19.153
HttpPost httpPost = new HttpPost(url[2]);
List<NameValuePair> nameValuePairs = new ArrayList<>(1);
nameValuePairs.add(new BasicNameValuePair("order", order));
try {
// Add name data to request
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpClient.execute(httpPost);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
return EntityUtils.toString(entity);
}
return "Error: " + response
.getStatusLine()
.getStatusCode() + " " + response
.getStatusLine().getReasonPhrase();
} catch (ClientProtocolException e) {
return e.getMessage();
} catch (IOException e) {
return e.getMessage();
}
}
@Override
protected void onPostExecute(String jsonResponse) {
Gson gson = new Gson();
tours = (gson.fromJson(jsonResponse, Tours.class));
Toast.makeText(context, jsonResponse, Toast.LENGTH_LONG).show();
}
and on the Server side:
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String asyncMessage = req.getParameter("order");
if(asyncMessage.equals("tours")){
m_tours = getTours(); //ArrayList<Tour> m_tours;
Tours tours = new Tours(m_tours);
resp.setContentType("application/json");
PrintWriter out = resp.getWriter();
out.print(new Gson().toJson(tours));
out.flush();
resp.getWriter().print(m_tours);
}
}
but I get an error:
03-23 13:27:09.523 32387-32387/madapps.bicitourbo E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: madapps.bicitourbo, PID: 32387
com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 692 path $
at com.google.gson.Gson.assertFullConsumption(Gson.java:786)
at com.google.gson.Gson.fromJson(Gson.java:776)
at com.google.gson.Gson.fromJson(Gson.java:724)
at com.google.gson.Gson.fromJson(Gson.java:696)
at madapps.bicitourbo.ServletPostAsyncTask.onPostExecute(ServletPostAsyncTask.java:92)
at madapps.bicitourbo.ServletPostAsyncTask.onPostExecute(ServletPostAsyncTask.java:36)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(Native Method)
Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 692 path $
This error occurs on the line:
Tour tours = (gson.fromJson(jsonResponse, Tours.class));
What do I do wrong?
* EDIT2 * Solved:
The error: Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON
was due to the fact that I was calling resp.getWriter().print()
two times, as suggested by @orip. Thank you!