Kike GM Kike GM - 6 months ago 61
Android Question

Retrofit null response in a success request 200

when I try to login in my system it return a User object from backend, and it is returning this json with http 200:

{
"data": [1]
0:{
"id": 14
"name": "Adam"
"email": "email@gmail.com"
"password": "adam"
"avatar": ""
"activity": ""
"bio": ""
"member_since": "0000-00-00"
"remember_token": null
"created_at": "2016-05-17 17:10:42"
"updated_at": "2016-05-17 17:10:42"
}-
-
}


All is apparently ok.
But in Android studio I obtain a null object when I'm access to response.body()

My method in the interface for login is this:

@GET("users/{name}/{password}")
Call<UserDTO> login(@Path("name") String name, @Path("password") String password);


And this is the part I obtain the error:

Call<UserDTO> call = mRestApi.getService().login(email, password);

call.enqueue(new Callback<UserDTO>() {
@Override
public void onResponse(Call<UserDTO> call, Response<UserDTO> response) {
//call.cancel();
if(response.code() == 401) //login incorrecto
{
onLoginFailed();

}else if(response.code() == 200) {
//TODO usuario nulo al venir de una peticion rest

Log.d("DEBUG", response.body().getUser().getName());
onLoginSuccess();
}
}

@Override
public void onFailure(Call<UserDTO> call, Throwable t) {
call.cancel();
Toast.makeText(getBaseContext(), "Error de conexión al servidor", Toast.LENGTH_LONG).show();
}
});


In this line it is failing:

Log.d("DEBUG", response.body().getUser().getName());


Finally Android Studio's error:

FATAL EXCEPTION: main
Process: myapp.myapp, PID: 3349
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String myapp.flattomate.Model.User.getName()' on a null object reference


I'm using now DTO pattern, but without this I obtain the same error.

What is happening?

EDIT
Retrofit class:

public class restAPI {

private static final String ENDPOINT = "http://192.168.2.102:8000/";
private final FlattomateService mService;

public interface FlattomateService{
@GET("users/{username}")
Call<User> getUser(@Path("username") Integer username);

@GET("users/index")
Call<List<UserDTO>> allUsers();

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);

@POST("users")
Call<User> register(@Body User user);

@GET("users/{name}/{password}")
Call<UserDTO> login(@Path("name") String name, @Path("password") String password);


}

public restAPI(){
Gson gson = new GsonBuilder()
.serializeNulls()
.excludeFieldsWithoutExposeAnnotation()
.create();

Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ENDPOINT)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();

mService = retrofit.create(FlattomateService.class);
}

public FlattomateService getService(){ return mService; }


}


UserDTO.java:

public class UserDTO {

User user;

public User getUser() { return user; }
}


User.java:

public class User {

@SerializedName("id")
@Expose
private Integer id;
@SerializedName("name")
@Expose
private String name;
@SerializedName("email")
@Expose
private String email;
@SerializedName("avatar")
@Expose
private String avatar;
@SerializedName("activity")
@Expose
private String activity;
@SerializedName("bio")
@Expose
private String bio;
@SerializedName("member_since")
@Expose
private String memberSince;

@SerializedName("password")
private String password;

public User(){}

public User(String name, String email, String password){
this.name = name;
this.email = email;
this.password = password;

}
/**
*
* @return
* The id
*/
public Integer getId() {
return id;
}

/**
*
* @param id
* The id
*/
public void setId(Integer id) {
this.id = id;
}

/**
*
* @return
* The name
*/
public String getName() {
return name;
}

/**
*
* @param name
* The name
*/
public void setName(String name) {
this.name = name;
}

/**
*
* @return
* The email
*/
public String getEmail() {
return email;
}

/**
*
* @param email
* The email
*/
public void setEmail(String email) {
this.email = email;
}

/**
*
* @return
* The avatar
*/
public String getAvatar() {
return avatar;
}

/**
*
* @param avatar
* The avatar
*/
public void setAvatar(String avatar) {
this.avatar = avatar;
}

/**
*
* @return
* The activity
*/
public String getActivity() {
return activity;
}

/**
*
* @param activity
* The activity
*/
public void setActivity(String activity) {
this.activity = activity;
}

/**
*
* @return
* The bio
*/
public String getBio() {
return bio;
}

/**
*
* @param bio
* The bio
*/
public void setBio(String bio) {
this.bio = bio;
}

/**
*
* @return
* The memberSince
*/
public String getMemberSince() {
return memberSince;
}

/**
*
* @param memberSince
* The member_since
*/
public void setMemberSince(String memberSince) {
this.memberSince = memberSince;
}


}

Answer

The problem was the json laravel send:

$response = Response::make(json_encode(['data'=>$user]), 200)->header('Location', $BASE_URL.$user->id)->header('Content-Type', 'application/json');
    return $response;

Laravel was sending an array that retrofit doesn't knew how to treat.

The solution was just send the $user like this:

$response = Response::make(json_encode($user), 200)->header('Content-Type', 'application/json');