How I can get json request body?
App.getApi().method(data).enqueue(new Callback<Obj>() {
#Override
public void onResponse(Call<Obj> call, Response<Obj> response){
// print here
}
...
};
If you are trying to print request / response while using retrofit you can enable logging check this article for same.
Related
I'm using Retrofit2 for the first time and have a few issues.
This is the code snippet used to call the REST API
//building retrofit object
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.0.71:9000/api/uniapp/")
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.build();
APIService service = retrofit.create(APIService.class);
//defining the call
Call<String> call = service.refreshAppMetaConfig("0");
//calling the api
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
//displaying the message from the response as toast
System.out.println("Uniapp :"+response);
}
#Override
public void onFailure(Call<String> call, Throwable t) {
System.out.println("Uniapp :"+t.getMessage());
}
});
This is the APIService class :
public interface APIService {
//The register call
#FormUrlEncoded
#POST("appmetaconfigjson")
Call<String> refreshAppMetaConfig(#Field("versionId") String versionId);
}
I'm using Play framework for creating the REST API. I am getting an internal server error. The API is not able to read the JSON request. But if I hit the API through Postman, it returns the response. Any suggestions?
Ive added the postman request screenshot.
As I can see from your screenshots of Postman, you're sending JSON body to REST API. When you select body type as raw - application/json in Postman, it automatically includes
Content-Type:application/json
as header. Hence, the request is successful in Postman.
Now, in order to make it work above request successfully in your Android application, you need to set headers with the request you send to REST API.
In APIService interface do the below changes.
import retrofit2.http.Body;
import okhttp3.ResponseBody;
import java.util.Map;
public interface APIService {
//The register call
// #FormUrlEncoded <==== comment or remove this line
#Headers({
"Content-Type:application/json"
})
#POST("appmetaconfigjson")
Call<ResponseBody> refreshAppMetaConfig(#Body Map<String, String> versionId);
}
Remove or comment #FormUrlEncoded annotation as we're sending JSON not FormUrlEncoded data.
Add #Headers() annotation with Content-Type:application/json
Change method parameter to #Body Map<String, String> versionId. The #Body annotation converts (serializes) Map (HashMap) data into JSON body when you request to API.
Change return parameter from String to ResponseBody.
Use the above-modified method as below
// code...
//defining the call
// create parameter with HashMap
Map<String, String> params = new HashMap<>();
params.put("versionId", "0");
Call<ResponseBody> call = service.refreshAppMetaConfig(params);
//calling the api
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
//displaying the message from the response as toast
// convert ResponseBody data to String
String data = response.body().string();
System.out.println("Uniapp : " + data);
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
System.out.println("Uniapp : " + t.getMessage());
}
});
Here also you need to change parameter from Call<String> to Call<ResponseBody>. And convert the response inside onResponse() method using response.body().string();.
This is not a duplicate question.
I am using Retrofit 2.0 and json for network tasks.
Also I am not using GSON to parse json instead I am using simple JsonObject and JsonArray to get model objects from json string.
Firstly guide me which retrofit converter must be used for above scenario.
Secondly, I am not able to get json string as response string.
I tried two approaches -
Approach 1 - I used Call< Void >. In this case the response.body() returns null though status code is 200.
Approach 2 - I used Call< ResponseBody >. In this case call.enqueue methods call 'on failure method' instead of 'onSuccess' and also the response body is null.
The status code is 200 in this case also.
Please suggest how to get the json string as response from retrofit 2.0.
you need to use JsonObject instead of Void or ResponseBody. Your code should be
Call<JsonObject> getCall = request.getDataCall();
getCall.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
}
});
Note : make sure you are using com.google.gson.JsonObject
When REST Api returns 404, onResponse called with NULL Response. We have user search api and if the user is not found on the server our REST api returns 404 with error response in body with more details.
As Retrofit 2.0 returns a null response body, it's hard for us to show the correct error to the user.
Do we have an alternate solution to get a response during 404?
Response:
{"responseStatus":{"code":"00297","severity":"ERROR","message":"Profile not found..","info":"","status":404}}
HTTP Status Code:
404
Thanks
Retrofit 2.0 shouldn't be returning a null response. If you are making an async callback and want the handle the error it should look something like this
// Create a very simple REST adapter which points the GitHub API.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
// Create an instance of our GitHub API interface.
GitHub github = retrofit.create(GitHub.class);
// Create a call instance for looking up Retrofit contributors.
Call<List<Contributor>> call = github.contributors("square", "retrofit");
call.enqueue(new Callback<ArrayList<Item>>() {
#Override
public void onResponse(Call<ArrayList<Item>> call, Response<ArrayList<Item>> response) {
if(response.isSuccessful()) {
// do something
}
else {
Log.e("Error Code", String.valueOf(response.code()));
Log.e("Error Body", response.errorBody().toString());
//display the appropriate message...
}
}
#Override
public void onFailure(Call<ArrayList<Item>> call, Throwable t) {
}
});
Some of that code was copied from Retrofit Samples. If you are getting a null response on a 404 something else is going wrong.
My web server returns JSON in the following form if successful (200 status code):
{"success":true,"data":{"user_id":"20","username":"Bob"}}
But if something went wrong (for example, if the username and password entered was too short in a form), it returns JSON in the following form (400 status code):
{"success":true,"errors":{"username":["Username too short"],"password":["Incorrect password","Password too short"]}}
How do I handle these two different responses in Retrofit? This is my code so far:
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(URL)
.build();
ApiEndpointInterface api = restAdapter.create(ApiEndpointInterface.class);
api.getToken('1', new Callback<DefaultResponse>() {
#Override
public void success(DefaultResponse json, Response response) {
//
}
#Override
public void failure(RetrofitError response) {
//
}
});
How do I handle these two differently structured JSON responses?
You need to do two things.
First, do not return a 400 from the server. as others have stated you actually have a successful response from the server, so you just need to parse the error on your end.
your server can return a flag indicating login success or failure.
After that, you can simply add the error model to your DefaultResponse model. like so
public class DefaultResponse {
public boolean success;
public DataModel data;
public ErrorModel errors;
public static class DataModel {
private String user_id;
private String username;
}
public static class ErrorModel { ... }
}
You will still need to handle instances where your server responds with statuses other than OK, but typically error responses from a server are simple plain text, like "bad request".. You could of course insert json if you wish which you could extract from RetrofitError.getMessage(), but GSON wouldn't parse that for you automatically. I hope this helps!
You should realize that actually both responses you posted are success from the network request perspective.
The failure status is for the request failure (Network connection error, 404, etc.) and not failure you return after trying to login the user in your backend.
You'll need to parse the result in success method and decide weather the internal result is success from your app logic perspective.
You should offcourse also handle failure().
if you get the JSON from your web service, which mean it's success.
so, in your success method, grab the JSON and handle it
for example, from your JSON format
#Override
public void success(DefaultResponse json, Response response) {
try {
JSONObject json = new JSONObject(json);
JSONObject data = json.get("data"); // if no "data" element, it will throw JSONException
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),"username to short",Toast.LENGTH_SHORT).show();
}
}
or you can use GSON to handle your JSON data
I'm using retrofit to call a web service and retrofit is throwing a failure, the the message from the 'Throwable` is giving me
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
I'm assuming that this is because the .Net web service is throwing an error and not returning JSON. But to prove this I need to be able to see the raw response in the onFailure. Is there anyway I can do this?
this is the code I'm using
public void userLoginRequestEvent(final AuthenticateUserEvent event) {
Call call = sApi.login(event.getUsername(), event.getPassword(), OS_TYPE, DeviceInfoUtils.getDeviceName());
call.enqueue(new Callback<LoggedInUser>() {
#Override
public void onResponse(Response<LoggedInUser> response, Retrofit retrofit) {
// response.isSuccess() is true if the response code is 2xx
if (response.isSuccess()) {
LoggedInUser user = response.body();
AppBus.getInstance()
.post(new UserIsAuthenticatedEvent(user, event.getUsername(),
event.getPassword()));
} else {
int statusCode = response.code();
// handle request errors yourself
}
}
#Override
public void onFailure(Throwable t) {
// handle execution failures like no internet connectivity
Log.d("ERROR", t.getMessage());
}
});
You can use the log interceptor that exists in the okhttp-logging-interceptor.
A good example can be found in Logging with Retrofit 2 as well.
Your server answer is just a string, not an object. Use an Interceptor to see your received response.
Add incerceptor dependency
compile 'com.squareup.okhttp3:logging-interceptor:3.4.0'
and then add it to your custom OkHttp client.
OKHttp client = ....
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
client.interceptors().add(interceptor);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("url")
.client(client) // add custom OkHttp client
You can check for BASIC, HEADERS and BODY. In your case you check for BODY to see body that you send and what server is sending as response body.