Dimkin
Dimkin

Reputation: 690

POST request to REST service in AsyncTask

I'm writing some small android application that works with REST services. The base structure of the response is: { result: "ok/error", message: "some string", entity: "either object or error description" }

The entity type is different each time whether the response is ok or error. Now, I'm calling the service from AsyncTask and I need to return the result to the UI thread.

I'm using gson library to desirialize the JSON from the server. The problem is that I do not have the ability to know what type of response I've got (ok or error).

Also, the AsyncTask can return only single type to the UI thread. Below is an example for what I could come up with. I need to state that I'm not a java programmer and I may not know all the patterns and maybe I miss something.

Anyway, I'll be glad for any help.

public class RegisterProxyAsync extends AsyncTask<User, String, Object> {

@Override
protected Object doInBackground(User... params) {
    try {
        Gson gson = new Gson();
        String request = gson.toJson(params[0]);

        HttpClient client = new DefaultHttpClient();
        HttpPost postAction = new HttpPost("http://SomeServiceEndpoint/register");
        postAction.addHeader(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
        postAction.setEntity(new StringEntity(request));

        HttpResponse response = client.execute(postAction);
        if (response != null) {
            InputStream stream = response.getEntity().getContent();
            String strResult = CharStreams.toString(new InputStreamReader(stream));
            try {
                UserResponse userResponse = gson.fromJson(strResult, UserResponse.class);
                return userResponse;
            } catch (Exception e) {
                ErrorResponse errorResponse = gson.fromJson(strResult, ErrorResponse.class);
                return errorResponse;
            }

            Log.e("debug", strResult);
        }
    } catch (Exception e) {
        // TODO:Handle exception
        e.printStackTrace();
    }

    return null;
}

@Override
protected void onPostExecute(Object result) {
    // TODO: execute some work
}

}

EDIT: I've changed the server to return proper HttpCodes (200 for success, 400 for error) but, I still have the problem of returning two different types of object from the doinbackground method, one for error and another for success.

Upvotes: 0

Views: 1148

Answers (1)

Perception
Perception

Reputation: 80633

A proper REST service should include an HTTP response code indicating the status of the processed request. If you have control over the service then I would recommend altering it to return a variant of 40x or 50x codes, to signal that an error has occurred. The service should only return a 200 OK if the request succeeded. On your client side, you would then parse the response based on the status code (normal entity for 200 ok, error entity for anything else). Pseudocode:

if(response.getStatusLine().getStatusCode() == 200) {
    UserResponse userResponse = gson.fromJson(strResult, UserResponse.class);
} else {
    ErrorResponse errorResponse = gson.fromJson(strResult, ErrorResponse.class);
}

If you can't change the server side for whatever reason, then on your client side you will have to use a generic JsonObject to parse the response. Pseudocode:

JSONObject jsonObj = new JSONObject(strResult);
if("ok".equals(jsonObj.get("result")) {
    return gson.fromJson(jsonObj.toString(), UserResponse.class);
} else {
    return gson.fromJson(jsonObj.toString(), ErrorResponse.class);
}

Upvotes: 1

Related Questions