I am receiving a body from my API call but onResponse() is not getting called, here are the methods:
final Rest_manager_league rest = new Rest_manager_league();
Call<List<Root>> listCall = rest.getMLeague_conn().getLeague(x);
listCall.enqueue(new Callback<List<Root>>() {
#Override
public void onResponse(Call<List<Root>> call, Response<List<Root>> response) {
lg = response.body();
Log.d("res", "ON");
if (response.isSuccessful()){
textView.setText(lg.get(3).getStanding().get(2).getTeamName());
Log.d("s", "true");
}
}
#Override
public void onFailure(Call<List<Root>> call, Throwable t) {
Log.d("Failure", "Failed");
}
});
Here is the Retrofit interface & the service:
public interface league_Conn {
#GET("/v1/soccerseasons/{id}/leagueTable")
#Headers("X-Auth-Token:" +
"1869f69f772b40a2a12fd6eefb4e48ef ")
Call<List<Root>> getLeague(#Path("id") int id);
}
public class Rest_manager_league {
private league_Conn mleague_conn;
public league_Conn getMLeague_conn() {
if (mleague_conn == null) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(logging).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://api.football-data.org/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
mleague_conn = retrofit.create(league_Conn.class);
}
return mleague_conn;
}
}
In the logcat, onFailure() is showing up. Like so:
okhttp3 <-- END HTTP (8300 byte body) Failer :Failed
Why is onResponse() not getting called?
You are getting a response body (8300 bytes) but onFailure is getting called, because your returned body does not agree with your GSONFactory. The deserialization process did not work. You can pinpoint the problem by printing a stack trace as #yazan pointed out. Just type:
t.printStackTrace()
in onFailure().
Edit:
The error occurs because you're telling Retrofit that you're expecting a list but instead you're getting a JSON object. I took a quick look at the API that you're using and it looks like it returns a JSON object and the returned object then contains the list you're interested in accessing. Try replacing instances of List<Root> to just Root. For more help, you can also check this question:
GSON throws Expected BEGIN_ARRAY but was BEGIN_OBJECT error
Related
I need to get the XML file from the site. I'm learning to use Retrofit.
I need to make a request and attach my API key via the "X-AppId" header. It should look like this:
X-AppId: my key.
If I do this from the browser, I get the answer.
Through the retrofit I get the access
error 403 Forbidden code = 403, message = Forbidden, url = https: //
Tell me how it is implemented properly to receive an answer from the server code = 200
Here is my implementation:
public interface myAPIinterface {
#GET("/api/ru/index/route/?from=Minsk&to=Warsaw")
Call<Routes> getProducts();
}
This is the activity where I output to the log:
private void getProducts(){
final ProgressDialog loading = ProgressDialog.show(this,"Fetching Data","Please wait...",false,false);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
Log.d(TAG, "getProducts");
httpClient.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.addHeader("X-AppId:", "97377f7b702d7198e47a2bf12eec74")
.build();
return chain.proceed(request);
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://rasp.rw.by")
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
myAPIinterface api = retrofit.create(myAPIinterface.class);
Call<Routes> call = api.getProducts();
call.enqueue(new Callback<Routes>() {
#Override
public void onResponse(#NonNull Call<Routes> call, #NonNull Response<Routes> response) {
Log.d(TAG, "onResponse");
Log.d(TAG, String.valueOf(kk));
Log.d(TAG, String.valueOf(response));
loading.dismiss();}
#Override
public void onFailure(Call<Routes> call, Throwable throwable) {
loading.dismiss();
Log.d(TAG, "onFailure" + throwable);
}
});
this is a log:
Response{protocol=http/1.1, code=403, message=Forbidden,
url=https://rasp.rw.by/api/ru/index/route/?from=Minsk&to=Warsaw}
if I take third-party sites where there are no headers, I get a response of 200 without problems. What am I doing wrong in this case? Thank you.
Oh, man, what are you doing. You can use annotations like #Query, #Header, etc.
public interface myAPIinterface {
#GET("/api/ru/index/route")
Call<Routes> getProducts(#Header("X-AppId:") String YOUR_APP_ID,
#Query("from") String from,
#Query("to") String to)
}
Then you can create request like this:
Retrofit retrofit = new Retrofit.Builder().
.baseUrl("https://rasp.rw.by")
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
retrofit.create(myAPIinterface.class).getProducts(myId, "Minsk", "Warsaw").enqueue ...
How It can help? You forgot to add header at second retrofit and then you have 403 error. So, You must add annotations, and this will be the last mistake when you forgot to put value to header/query/etc.
I am using Retrofit2 for the first time and have a problem to get a simple Array in non JSON format.
Error: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 3 path $[0]
This means its not an JSON Object since it does not start with "{"
I tried adding the ScalarsConverter but it doesent seems to work.
Api: https://chasing-coins.com/api/v1/coins
Interface:
public interface Retro_coins {
#GET("api/v1/coins")
Call<List<Coinlist>> getCoinlist();
}
Class:
public class Coinlist {
private List coinlist;
public List getCoinlist() {
return coinlist;
}
}
Retrofit initialization and call:
String API_BASE_URL = "https://chasing-coins.com/";
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
;
Retrofit retrofit = builder.client(httpClient.build()).build();
Retro_coins client = retrofit.create(Retro_coins.class);
// Fetch list
Call<List<Coinlist>> call =
client.getCoinlist();
// Execute the call asynchronously. Get a positive or negative callback.
call.enqueue(new Callback<List<Coinlist>>() {
#Override
public void onResponse(Call<List<Coinlist>> call, Response<List<Coinlist>> response) {
// The network call was a success and we got a response
Log.w("Yes", response.toString());
}
#Override
public void onFailure(Call<List<Coinlist>> call, Throwable t) {
Log.w("no", t.toString());
}
});
Thanks!
When you are using private List coinlist;, Gson expects the object to be
{
"coinlist":"[]"
}
where as what you are providing is just
["String","String","String"]
furthermore when you use Call<List<Coinlist>> you are expecting the data to be
[
{
"coinlist":"[]"
}
]
Just change your call from Call<List<Coinlist>> to Call<List<String>>. That should fix your problem. Let me know if you need more clarification
Your request Returning String. So you need to Change the Response to String or Need to change your request Call to String.
I'm trying to do a POST, but its returning me a error :
com.google.gson.stream.MalformedJsonException: Use
JsonReader.setLenient(true) to accept malformed JSON at line 1 column
1 path $
My Call:
#POST("BuscaPontos")
Call<PontuacaoModel> postPontuacao(#Body PontuacaoModel model);
And my Webservice consum:
try
{
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL_BUSCAR_CIDADE)
.addConverterFactory(GsonConverterFactory.create(new Gson()))
.build();
PontuacaoModel model = new PontuacaoModel();
model.setNome("Juina");
model.setEstado("Mato Grosso");
CallService.Pontuacao callService = retrofit.create(CallService.Pontuacao.class);
Call<PontuacaoModel> requestService = callService.postPontuacao(model);
requestService.enqueue(new Callback<PontuacaoModel>() {
#Override
public void onResponse(Call<PontuacaoModel> call, Response<PontuacaoModel> response) {
if(response.isSuccessful())
{
String i = response.message().toString();
}
}
#Override
public void onFailure(Call<PontuacaoModel> call, Throwable t) {
String i = t.toString();
}
});
}
catch (Exception ex)
{
}
Whats is wrong ?
I don't see a line in your code where you add client during initializing retrofit:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL_BUSCAR_CIDADE)
.client() // add a client instance here, e.g. OkHttpClient
.addConverterFactory(GsonConverterFactory.create(new Gson()))
.build();
This is the issue with your response from server, that may not be correct format. Please install a tool called postman form here.
Use this tool to check whether the response is correct before do some coding.
I am using Retrofit library (version 2.0.2 as of this writing).
I am making a GET call to a service which responds a big JSON object but I am only interested in one key:value pair in it.
How can I get just that instead of writing a whole new POJO class that matches the JSON response?
Example -
{
status_code: 34,
status_message: "The resource you requested could not be found.",
...,
...
}
I need only status code value (34 here).
Please note, I am just giving an example of this JSON object here. The real one I am dealing with is huge and I care about only one key:value pair in it.
Thanks in advance.
You can refer to the following:
#GET("/files/jsonsample.json")
Call<JsonObject> readJsonFromFileUri();
and
class MyStatus{
int status_code;
}
...
Retrofit retrofit2 = new Retrofit.Builder()
.baseUrl("http://...")
.addConverterFactory(GsonConverterFactory.create())
.build();
WebAPIService apiService = retrofit2.create(WebAPIService.class);
Call<JsonObject> jsonCall = apiService.readJsonFromFileUri();
jsonCall.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
String jsonString = response.body().toString();
Gson gson = new Gson();
MyStatus status = gson.fromJson(jsonString, MyStatus.class);
Log.i(LOG_TAG, String.valueOf(status.status_code));
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.e(LOG_TAG, t.toString());
}
});
...
Debug screenshot
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.