I have 500 internal server error, every time when i try to send POST request via Retrofit. When i sending GET request, it sending correctly. I'm sure that with serverside everyting is ok. What's wrong with my code ?
String ENDPOINT = "http://52.88.40.210";
//model for request
FriendModel ff = new FriendModel();
ff.setFriendNumber("380935275259");
ff.setId(516);
ff.setNumber("380936831127");
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(ENDPOINT)
.build();
WayfAPI api = adapter.create(WayfAPI.class);
api.getFriendsLocation(ff, new Callback<List<FriendLocationModel>>() {
#Override
public void success(List<FriendLocationModel> friendLocationModels, Response response) {
for (FriendLocationModel ff : friendLocationModels) {
Log.d("myLogs", "===========Successful==========");
Log.d("myLogs", "Id: " + ff.getId());
Log.d("myLogs", "Number: " + ff.getNumber());
Log.d("myLogs", "GeoLocation: : " + ff.getGeoLocation());
}
}
#Override
public void failure(RetrofitError error) {
Log.d("myLogs", "-------ERROR-------");
Log.d("myLogs", Log.getStackTraceString(error));
}
});
}
Declaration of request:
#Headers({
"Accept: application/json",
"Content-type: application/json"
})
#POST("/api/geo/getLoc")
public void getFriendsLocation(#Body FriendModel friendModel, Callback<List<FriendLocationModel>> response);
Exampe of request and response from Postman:
It seems that in postman you're sending an array of FriendModel, but in your code you're sending a single object.
Just change the object you're sending, and instead of sending a single object, send a List as the server expects
List<FriendModel> friendsList = new ArrayList<FriendModel>();
FriendModel ff = new FriendModel();
ff.setFriendNumber("380935275259");
ff.setId(516);
ff.setNumber("380936831127");
friendsList.add(ff);
You should also change this signature:
public void getFriendsLocation(#Body FriendModel friendModel, Callback<List<FriendLocationModel>> response);
to
public void getFriendsLocation(#Body List<FriendModel> friendModel, Callback<List<FriendLocationModel>> response);
Related
I'm trying to represent the below curl request in android using Retrofit,
curl -i -X POST \
https://graph.facebook.com/v13.0/1234567890/messages \
-H 'Authorization: Bearer ucuzZCQv9qb--token--0UMHaEhLwvuOW6WvapUGuPAkrDchj' \
-H 'Content-Type: application/json' \
-d '{ "messaging_product": "whatsapp", "to": "9477number", "type": "template", "template": { "name": "hello_world", "language": { "code": "en_US" } } }'
My API Service class
public interface APIService {
#POST("{phoneNoId}/messages")
Call<MsgResponse> SendMsg(#Path("phoneNoId") String phoneNoId,
#Header("Authorization") String authorization,
#Header("Content-Type") String types,
#Body String msgObj
);
}
My API calling place in the MainActivity.class
APIService apiService=RetroInstance.getRetrofitClient().create(APIService.class);
Call<MsgResponse> call=apiService.SendMsg("100798385993185",
"Bearer 5iWIZBiI5vogoNZBKbBJ0oZAibvZBG---token--xIcDPoW",
"application/json",
jsonBody
);
Log.d(TAG, "onCreate: "+call.toString());
call.enqueue(new Callback<MsgResponse>() {
#Override
public void onResponse(Call<MsgResponse> call, Response<MsgResponse> response) {
Log.d(TAG, "onResponse: "+response.toString());
}
#Override
public void onFailure(Call<MsgResponse> call, Throwable t) {
Log.d(TAG, "onFailure: "+t.getMessage());
Log.d(TAG, "onFailure: "+t.getStackTrace().toString());
}
});
here jsonbody I'm getting the json object using gson like below String jsonBody=gson.toJson(msgObj);
My Request is successful but I'm getting 400 error code error message below, what went wrong here, Thank you
onResponse: Response{protocol=h2, code=400, message=, url=https://graph.facebook.com/v12.0/1234567890/messages}
You can pass headers to your Retrofit request using Interceptor. This might not be a perfect way, but it works quite good, These headers are sent with every API request.
First, extend Interceptor and add the header to the request as shown below:
class LoggingInterceptor implements Interceptor {
#Override public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
Request newRequest = request.newBuilder()
.header("Authorization","YOUR AUTH CODE HERE")
.header("Content-Type","application/json").build();
return chain.proceed(newRequest);
}
}
Now you can use this custom Interceptor with OkHttpClient :
OkHttpClientBuilder builder = OkHttpClient.Builder()
.addInterceptor(new MyInterceptor());
Use this client while building the Retrofit object:
Retrofit.Builder()
.baseUrl(YOUR_BASE_URL)
.client(okHttpClientBuilder.build())
.build()
Using Retrofit I post my contact list on the phone without authentication. I need to do retrofit basic authentication, but as far as I can't see from the internet. Can you help me, please?
This is my Code:
public void GetContactsIntoArrayList(){
mAPIService = ApiUtils.getAPIService();
final User user = new User();
final Post post = new Post();
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null, null, null);
while (cursor.moveToNext()) {
int i = 0;
name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
phonenumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
StoreContacts.add(name + " " + ":" + " " + phonenumber);
user.setphoneNumber(phonenumber.toString().trim());
user.setname(name.toString().trim());
List<User> phoneList = new ArrayList<>();
phoneList.add(user);
post.setUsers(phoneList);
sendPost(post);
}
cursor.close();
}
public void sendPost(Post post){
mAPIService.savePost(post).enqueue(new Callback<Post>() {
#Override
public void onResponse(Call<Post> call, Response<Post> response) {
Log.d("requestError", "onResponse: "+ call.request().body().toString());
if(response.isSuccessful()) {
Log.i("Is Ok?","OK :)");
}
}
#Override
public void onFailure(Call<Post> call, Throwable t) {
}
});
}
This is so far the easiest method i have ever tried for "Basic Authentication".
Use the below code to generate the auth header (API/Repository class)
var basic = Credentials.basic("YOUR_USERNAME", "YOUR_PASSWORD")
Pass this as header to the webservice call (API/Repository class)
var retrofitCall = myWebservice.getNewsFeed(basic)
Add the basic header as parameter (Retrofit Webservice interface class)
#GET("newsfeed/daily")
fun getNewsFeed(#Header("Authorization") h1:String):Call<NewsFeedResponse>
My code is in Kotlin, just in case you were looking for Java. But can be easily translated to Java.
References: https://mobikul.com/basic-authentication-retrofit-android/
You can add auth value in header of the request like if you want to send auth token then follow below step:
#POST("/auth/update-contactno")
#Headers(
"Content-Type: application/json",
Constants.headerApp,
Constants.headerLanguage,
Constants.headerPlatform,
Constants.headerVersion
)
fun updateMobileNumber(#Header(Constants.authorization) token: String?, #Body verifyForgotPasswordOTPInput: VerifyForgotPasswordOTPInput): Call<JsonObjectResponse<UserModel>>
And call updateMobileNumber() like :
apiService.updateMobileNumber(token, verifyForgotPasswordOTPInput)
I want to call SharePoint rest API form android. for this, i'm using cookies to call rest API using web view, but while calling am getting "BasicNetwork.performRequest: Unexpected response code 403".
if l call to SharePoint rest api using volley here what i tried up to.
update:i'm using this site for refrence SharePoint rest api from android
**Update:during research i found one example to connect with share point online using soap as well, any idea how to do that? **
private void sendAndRequestResponse() {
//RequestQueue initialized
Log.d(TAG, "Starting volley request to graph");
/* Make sure we have a token to send to graph */
RequestQueue queue = Volley.newRequestQueue(this);
JSONObject parameters = new JSONObject();
try {
parameters.put("key", "value");
} catch (Exception e) {
Log.d(TAG, "Failed to put parameters: " + e.toString());
}
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url,
parameters,new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
/* Successfully called graph, process data and send to UI */
Log.d(TAG, "Response: " + response.toString());
Toast.makeText(MainActivity.this, ""+response.toString(), Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "Error: " + error.toString());
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
headers.put("Cookie","rtFa=" + RTFA + "; FedAuth=" + FedAuth);
headers.put("Accept","application/json;odata=verbose");
headers.put("Content-type","application/json;odata=verbose");
return headers;
}
};
Log.d(TAG, "Adding HTTP GET to Queue, Request: " + request.toString());
request.setRetryPolicy(new DefaultRetryPolicy(
3000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.add(request);
}
I used rtfa and fed cookies to pass as header.
Update: i used share point login URL for windows auth. for and after success i store rfta and fed auth. cookies to pass token as header but i'm getting same error.
When I fail to parse the json from the server, I try to collect the situation.
I can see what the server gave me using the class that implements the Interceptor.(LoggingInterceptor)
However, I do not seem to be able to get the value in 'onFailure()', a situation where I need to collect errors. Because it only provides 'Call' and 'Throwable'. How do I get raw data from the server in 'onFailure()'?
Below is my code.
LoggingInterceptor
public class LoggingInterceptor implements Interceptor {
//로그에 쓰일 tag
private static final String TAG = CalyApplication.class.getSimpleName() + "/" + LoggingInterceptor.class.getSimpleName();
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
Response response = chain.proceed(request);
long t2 = System.nanoTime();
String responseString = new String(response.body().bytes());
//yes, I can see response in here. but I need it in 'onFailure()'.
Logger.i(TAG, "code : " + response.code() + "\n" + responseString);
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), responseString))
.build();
}
}
Actrivity
void fetchData(){
ApiClient.getService().test(
"test"
).enqueue(new Callback<BasicResponse>() {
#Override
public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
BasicResponse body = response.body();
switch (response.code()){
case 200:
break;
default:
break;
}
}
#Override
public void onFailure(Call<BasicResponse> call, Throwable t) {
//I want get Response object in here!
//but it only provides Call&Throwable
}
});
}
Thanks!
If you get a 4xx or 5xx (error)status code then the onResponse is called, not the onFailure. You get a response body(2xx) or error body accordingly only if the call was successful. So in onResponse you should have the following structure:
if (response.isSuccessful()) {
// Get response body
} else if (response.errorBody() != null) {
// Get response errorBody
String errorBody = response.errorBody().string();
}
Edit: More info about how to retrieve the errorBody can be found here.
I'm using retrofit 1.9.0 and I had tried the following code to get a response in json format:
public void Execute(String email, String password, Callback<User> callback) {
final Callback<User> cb = callback;
RestAdapter restAdapter = buildRestAdapter();
System.out.println("Email " + email + " passowrd " + password);
User user = new User();
user.setEmail(email);
user.setPassword(password);
restAdapter.create(YutonAPI.class).postLogin(
user,
new Callback<User>() {
#Override
public void success(User user, Response response) {
System.out.println("succes");
System.out.println(response.getBody());
}
#Override
public void failure(RetrofitError error) {
System.out.println("error "+ error);
}
});
}
So this line of code:
System.out.println(response.getBody());
Should give me a response in json format however it didn't work because I'm getting the following output:
Link: http://i.imgur.com/mBQs1LL.png
So this is how my response in json format should look like:
{
"user": {
"image": "https://www.gravatar.com/avatar/e0a190604dc3dd2ee7b66bb95c20ef7f?d=identicon&s=512"
"email": "a#hotmail.com"
"name": "a"
"id": "566dfac21043a31820bf1ae6"
} -
}
I had already tested it on my server where I was making a post request. Below you can see a screenshot of it:
Link: http://i.imgur.com/PtEMR12.png
The issue here is that response.getBody() returns a TypedInputStream object, which you can't directly output because it isn't a String.
To read a TypedInputStream there are several options, as posted in: Retrofit callback get response body, the easiest being:
String body = new String(((TypedByteArray) response.getBody()).getBytes());
If the following error is thrown:
java.lang.ClassCastException: retrofit.client.UrlConnectionClient$TypedInputStream cannot be cast to retrofit.mime.TypedByteArray
Then make sure that you set .setLogLevel(RestAdapter.LogLevel.FULL) on the RestAdapter that you use to create the service.