Ahsan Abdullah
Ahsan Abdullah

Reputation: 47

Getting 400 request from api server

I am working on my android app for which i am using POST request I am getting 400 bad request error

I think maybe their is a model class error i am not sure please respond

RetrofitInstance

public class RetrofitInstance {
private static Retrofit retrofit = null;
private static String BASE_URL = "http://<your ip address>:3000/";

public static Retrofit getService(){

    Gson gson = new GsonBuilder()
            .setLenient()
            .create();

    if(retrofit == null){
        retrofit = new Retrofit
                .Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();

    }
    return retrofit;
}
}    

API END POINT

public interface EndPoints {

    @FormUrlEncoded
    @POST("api/movie")
    Call<Movie> setMovie(@Field("title") String title,
                 @Field("genreId") String genreId,
                 @Field("numberInStock") int numberInStock,
                 @Field("dailyRentalRate") int dailyRentalRate);

    }

POSTMAN REQUEST AND RESPONSE FOR TESTING THAT API IS WORKING https://ibb.co/TkvDZFz

MODEL CLASS

Genre Pojo:

public class Genre{

    @SerializedName("name")
    private String name;

    @SerializedName("_id")
    private String id;

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public void setId(String id){
        this.id = id;
    }

    public String getId(){
        return id;
    }

    @Override
    public String toString(){
        return 
            "Genre{" + 
            "name = '" + name + '\'' + 
            ",_id = '" + id + '\'' + 
            "}";
        }
}

Movie POJO :

public class Movie{

    @SerializedName("dailyRentalRate")
    private int dailyRentalRate;

    @SerializedName("__v")
    private int V;

    @SerializedName("genre")
    private Genre genre;

    @SerializedName("_id")
    private String id;

    @SerializedName("title")
    private String title;

    @SerializedName("numberInStock")
    private int numberInStock;

    @SerializedName("genreId")
    private String genreId;

    public Movie(String title, String genreId, int numberInStock ,int dailyRentalRate) {
        this.dailyRentalRate = dailyRentalRate;
        this.title = title;
        this.numberInStock = numberInStock;
        this.genreId = genreId;
    }

    public void setDailyRentalRate(int dailyRentalRate){
        this.dailyRentalRate = dailyRentalRate;
    }

    public int getDailyRentalRate(){
        return dailyRentalRate;
    }

    public void setV(int V){
        this.V = V;
    }

    public int getV(){
        return V;
    }

    public void setGenre(Genre genre){
        this.genre = genre;
    }

    public Genre getGenre(){
        return genre;
    }

    public void setId(String id){
        this.id = id;
    }

    public String getId(){
        return id;
    }

    public void setTitle(String title){
        this.title = title;
    }

    public String getTitle(){
        return title;
    }

    public void setNumberInStock(int numberInStock){
        this.numberInStock = numberInStock;
    }

    public int getNumberInStock(){
        return numberInStock;
    }

    @Override
    public String toString(){
        return 
            "Movie{" + 
            "dailyRentalRate = '" + dailyRentalRate + '\'' + 
            ",__v = '" + V + '\'' + 
            ",genre = '" + genre + '\'' + 
            ",_id = '" + id + '\'' + 
            ",title = '" + title + '\'' + 
            ",numberInStock = '" + numberInStock + '\'' + 
            "}";
        }
}

Activity

public class MainActivity extends AppCompatActivity {

private Button click;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    click = findViewById(R.id.click);

    click.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            addMovieCall();
        }
    });
}

private void addMovieCall() {
    final EndPoints vidlyEndPoint = RetrofitInstance.getService().create(EndPoints.class);
    Call<Movie> call =  vidlyEndPoint.setMovie("intelRPG","5d7398d2bdc4d04960d60845",20,30);

    call.enqueue(new Callback<Movie>() {
        @Override
        public void onResponse(Call<Movie> call, Response<Movie> response) {
            if(!response.isSuccessful()){
                Log.e("Response", String.valueOf(response.code()));
                Log.e("Response", String.valueOf(response.message()));
            }
            else if(response.isSuccessful()){
                Log.e("Response", String.valueOf(response.body().getId()));
                Log.e("Response", String.valueOf(response.body().getTitle()));
                Log.e("Response", String.valueOf(response.body().getGenre().getName()));
                Log.e("Response", String.valueOf(response.body().getDailyRentalRate()));
                Log.e("Response", String.valueOf(response.body().getNumberInStock()));
                Toast.makeText(getApplicationContext(),"Posted Successfully",Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onFailure(Call<Movie> call, Throwable t) {
            Log.e("Response failed",t.getMessage());
        }
    });
}
 }

I expect the output of 200, but the actual output is 400.

Upvotes: 2

Views: 147

Answers (3)

Jakir Hossain
Jakir Hossain

Reputation: 3930

You can try like below.

JsonObject requestBody = new JsonObject();
            requestBody.addProperty("title", "intelRPG");
            requestBody.addProperty("genreId", "5d7398d2bdc4d04960d60845");
            requestBody.addProperty("numberInStock", "20");
            requestBody.addProperty("dailyRentalRate", "30");

Call<Movie> call =  vidlyEndPoint.setMovie(requestBody);
.....

API END POINT should be like below

@POST("api/movie")
Call<Movie> setMovie(@Body JsonObject jsonObject);

Upvotes: 0

Azamat Mahkamov
Azamat Mahkamov

Reputation: 1090

You have to make your values the same type as the required

@FormUrlEncoded
@POST("api/movie")
Call<Movie> setMovie(@Field("title") String title,
             @Field("genreId") String genreId,
             @Field("numberInStock") String numberInStock, 
             @Field("dailyRentalRate") String dailyRentalRate);

}

I would also suggest using One pojo class with @Body annotation.

By the way, to understand the network problem better, You'd better use chuck library, by just adding the Chuck as an Intercepter in okhttp object. It will show the real cause, help you to find the problem faster

https://github.com/jgilfelt/chuck

Upvotes: 3

Ashish
Ashish

Reputation: 6919

Change your interface call :

Call<Movie> setMovie(@Field("title") String title,
                     @Field("genreId") String genreId,
                     @Field("numberInStock") String numberInStock, // Needs String
                     @Field("dailyRentalRate") String dailyRentalRate);

    }

and call will be :

Call<Movie> call =  vidlyEndPoint.setMovie("intelRPG","5d7398d2bdc4d04960d60845","20","30");

Upvotes: 1

Related Questions