I am implementation for Retrofit on api call using images-upload base64Encode string. it is sending data perfect but Retrofit return response Internal Server Error 500 and i am sending request type is Body custom class. Plz help me what i do.
#Headers("Accept:application/json")
#POST(RestClient.postRegister)
Call<RegisterResp> getRegisterResponse(#Body RequestRegisterVo requestRegisterVo);
Call<RegisterResp> call = MyApplication.getRestClient().getApplicationServices().getRegisterResponse(requestRegisterVo);
call.enqueue(new Callback<RegisterResp>() {
#Override
public void onResponse(Call<RegisterResp> call, Response<RegisterResp> response) {
if (Other.isValidResp(response)) {
// success Log.i(TAG,"Register successfully");
} else {
hideDialog();
}
}
#Override
public void onFailure(Call<RegisterResp> call, Throwable t) {
hideDialog();
showToast(t.getMessage());
}
});
The same issue I had to face it, I got a solution in my case-
there is parameter issue, I was sending parameters in String and at the backend, they required Integer parameters.
You also checkout may be there is the issue with parameters or second reason is the URL issue so check it URL also.
Related
I get error when I try to make request with retrofit in my android application.
I get 500 Interval Server Error
"title":"Internal Server
Error","status":500,"detail":"JSONObject[\"response\"] not
found.","path":"/api/profiles/help/45.13367991428822/33.5960291326046","message":"error.http.500"
Here is my code:
IApiService service = RetrofitInstance.getRetrofitAuthInstance().create(IApiService.class);
Call<ArrayList<Profile>> call = service.sendHelp(v1, v2);
call.enqueue(new Callback<ArrayList<Profile>>() {
#Override
public void onResponse(Call<ArrayList<Profile>> call, Response<ArrayList<Profile>> response) {
Toast.makeText(getBaseContext(), String.valueOf(response.code()), Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(Call<ArrayList<Profile>> call, Throwable t) {
Toast.makeText(getBaseContext(), t.getMessage(), Toast.LENGTH_LONG).show();
}
});
And my Interface:
#GET(Urls.SEND_HELP)
Call<ArrayList<Profile>> sendHelp(#Path("latitude") String latitude,
#Path("longitude") String longitude);
Please, help me.
Obviously problem is with object serialization on server side.
Status code 5xx stands for error that happened on server.
There is nothing you can do with your Retrofit client to fix it.
Before I get the obligatory "you shouldn't be testing real network responses for XYZ reasons!", it should be noted that I am not asking whether or not I should.
I am asking specifically how I would go about doing so, if I wanted to.
After a few hours of struggle I've successfully managed a proper response from Volley, and have that test going.
The problem I'm having now, is that call.enque(...) seems to hang on the RobolectricTestRunner. Unlike Volley, I can't peek in and see whats going on in there (for Volley, the challenge was not realizing that Looper.getMainLooper doesn't get properly created.)
So, all I am doing is trying to make a simple request to the server via Retrofit. The issue, as I said, is that the entire system hangs at call.enqueue, and there is no error or response ever (even when my await is longer). The network call works fine with volley, but I am getting this snag here with Retrofit. Here's the code if you want to try it. And of course, the function works fine when the app is running.
//in NetworkManager.class
public void someCall(HashMap properties, NetworkResponseListener listener){
this.okHttpClient = new OkHttpClient.Builder().cache(new Cache(appContext, 35 * 1024 * 1024)).build();
this.retrofit = new Retrofit.Builder().baseUrl(httpPath + apiHost).client(okHttpClient).build();
this.myService = retrofit.create(MyService.class);
Call call = myService.someRequest(properties);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
listener.onSuccess(response);
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
listener.onError(t);
}
});
}
Service:
interface MyService {
#GET("/api/SomeEndpoint/")
Call<ResponseBody> someRequest(#QueryMap Map<String, Object> params);
}
Test:
#Test
public void testSomeCall() throws Exception {
//Network class has setup OkHttpClient/Service/Retrofit already
NetworkResponseListener listener = new NetworkResponseListener() {
#Override
public void onSuccess(Response response) {
this.response = response;
}
#Override
public void onError(Throwable error) {
//
}
};
NetworkManager.someCall(this.properties, listener);
await().atMost(30, TimeUnit.SECONDS).until(ResponseReceived());
}
Everyone's response on stackoverflow has been 'don't test real network responses', which is really not helpful.
Solution is pretty much exactly the same as for volley.
Retrofit2 will default to the platform callback executor, which will not be correctly instantiated in a test.
Solution is simple. If you wish to test retrofit with real network calls, you must change the callbackExector. Here's what I ended up doing:
retrofit = new Retrofit.Builder().baseUrl(baseUrl)
.client(okHttpClient).callbackExecutor(Executors.newSingleThreadExecutor())
Network tests are running successfully.
I'm trying to upgrade to Retrofit 2.0 and add RxJava in my android project. I'm making an api call and want to retrieve the error code in case of an error response from the server.
Observable<MyResponseObject> apiCall(#Body body);
And in the RxJava call:
myRetrofitObject.apiCall(body).subscribe(new Subscriber<MyResponseObject>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(MyResponseObject myResponseObject) {
//On response from server
}
});
In Retrofit 1.9, the RetrofitError still existed and we could get the status by doing:
error.getResponse().getStatus()
How do you do this with Retrofit 2.0 using RxJava?
Instead of declaring the API call like you did:
Observable<MyResponseObject> apiCall(#Body body);
You can also declare it like this:
Observable<Response<MyResponseObject>> apiCall(#Body body);
You will then have a Subscriber like the following:
new Subscriber<Response<StartupResponse>>() {
#Override
public void onCompleted() {}
#Override
public void onError(Throwable e) {
Timber.e(e, "onError: %", e.toString());
// network errors, e. g. UnknownHostException, will end up here
}
#Override
public void onNext(Response<StartupResponse> startupResponseResponse) {
Timber.d("onNext: %s", startupResponseResponse.code());
// HTTP errors, e. g. 404, will end up here!
}
}
So, server responses with an error code will also be delivered to onNext and you can get the code by calling reponse.code().
http://square.github.io/retrofit/2.x/retrofit/retrofit/Response.html
EDIT: OK, I finally got around to looking into what e-nouri said in their comment, namely that only 2xx codes will to to onNext. Turns out we are both right:
If the call is declared like this:
Observable<Response<MyResponseObject>> apiCall(#Body body);
or even this
Observable<Response<ResponseBody>> apiCall(#Body body);
all responses will end up in onNext, regardless of their error code. This is possible because everything is wrapped in a Response object by Retrofit.
If, on the other hand, the call is declared like this:
Observable<MyResponseObject> apiCall(#Body body);
or this
Observable<ResponseBody> apiCall(#Body body);
indeed only the 2xx responses will go to onNext. Everything else will be wrapped in an HttpException and sent to onError. Which also makes sense, because without the Response wrapper, what should be emitted to onNext? Given that the request was not successful the only sensible thing to emit would be null...
Inside onError method put this to get the code
((HttpException) e).code()
You should note that as of Retrofit2 all responses with code 2xx will be called from onNext() callback and the rest of HTTP codes like 4xx, 5xx will be called on the onError() callback, using Kotlin I've came up with something like this in the onError() :
mViewReference?.get()?.onMediaFetchFinished(downloadArg)
if (it is HttpException) {
val errorCode = it.code()
mViewReference?.get()?.onMediaFetchFailed(downloadArg,when(errorCode){
HttpURLConnection.HTTP_NOT_FOUND -> R.string.check_is_private
else -> ErrorHandler.parseError(it)
})
} else {
mViewReference?.get()?.onMediaFetchFailed(downloadArg, ErrorHandler.parseError(it))
}
I have written a Retrofit code which has a Yii2 backend. The problem is: when I call the web-service on backend, it works perfectly. However, when I try to call the web-service from android device; it throws a response code of 404. Here is what I have done:
I am targeting a url which looks like: http://192.168.0.104/root-web/web/index.php?r= and it had an end-point: root/register
public interface RegisterAPIService {
#POST("practice/register")
Call<RegisterModel> registerUser(#Body RegisterDetails registerDetails);
}
The code in my activity looks like this..
RegisterDetails registerDetails = new RegisterDetails(email, mobile, password);
RegisterAPIService registerAPIService = retrofit.create(RegisterAPIService.class);
Call<RegisterModel> call =registerAPIService.registerUser(registerDetails);
call.enqueue(new Callback<RegisterModel>() {
#Override
public void onResponse(Response<RegisterModel> response) {
Log.d("Message", "code..."+response.code() + " message..." + response.message()+" body..."+response.body());
}
#Override
public void onFailure(Throwable t) {
}
});
} else {
// Error
}
}
I am getting 404 for the above code. I am trying to send my parameters in the form of a POST request. Please guide me through it.
You should call your development machine from the device, by its ip address, based on how they are connected. Also you can use Android Reverse Tethering tools for your operating system. for further study and options you can take a look at the answers to this question
I am making call using the following callback method:
Callback<PeopleList> callback = new Callback<PeopleList>() {
#Override
public void onResponse(Response<PeopleList> response) {
Toast.makeText(LoginActivity.this,getString(R.string.login_failed), Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Throwable t) {
Toast.makeText(LoginActivity.this,getString(R.string.login_failed), Toast.LENGTH_SHORT).show();
}
};
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
retrofit.create(MyService.class).getPeopleData().enqueue(callback);
To the following interface:
public interface MyService {
#Headers("Accept: application/json")
#GET("/data/people/")
Call<PeopleList> getPeopleData();
}
This callback works just fine on successful requests. On unsuccessful ones however it does not give me the opportunity to investigate further as the onFailure method does not allow me to retrieve the http error code that came with the response.
On investigating further I found that according to several stackoverflow threads, the onResponse method should be called even on unsuccessful requests. This however seems to be at odds not only with my personal experience but also with the documentation of the Callback interface, which states that:
Communicates responses from a server or offline requests. One and only one method will be
invoked in response to a given request.
So the question is, how do I get the HTTP error code from a failed response if the onResponse method isn't called?
I think that the onResponse method gets called even if there is a response with an Error so something like this might work(sorry if I did something wrong first attempt to answer anybody :)
#Override
public void onResponse(Response<PeopleList> response) {
if(response.isSuccess()){ //good http request, do something with response.body()....
Toast.makeText(LoginActivity.this,getString(R.string.login_failed), Toast.LENGTH_SHORT).show();
} else { //bad http response do something with error message
try {
Toast.makeText(LoginActivity.this,response.errorBody().string().toString(), Toast.LENGTH_SHORT).show();
} catch (IOException e){
//IOException caught from response.errorBody().string() method
}
}
}
onResponse() will be always called, for failed requests .body() is null. response.isSuccess() is used to quickly distinguish requests with http codes between 200 and 300.
If you want to access http codes you can do the following:
int htppResultCode = response.raw().code();
It accesses the raw Response object which holds information about general outcome of the request.