'Retrofit 2 sending from android client empty request body to spring boot in server with 200 status whereas in postman it works fine

I have been struggling hard to send a request body to server with one parameter to server from android client, which gives me 200 status on success but with an empty request body. It works all fine in postman with successful transaction.

API below is what i am calling

@POST("user/loginwithotp")
@Headers({
        "Content-Type: application/json;charset=UTF-8"
})
Call<ResponseAPI> saveMobile(@Body AuthenticationVO authenticationVO);

Below is the code for retrofit client

                     public static Retrofit getClient() {
        String baseUrl = "http://192.168.xx.xx:8080/dmp/";


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

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new   OkHttpClient.Builder().addInterceptor(interceptor).build();

      Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl) //if all api base url is same only add here. If not same then add url as string in “getClient()” method and then pass that here
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(client)
                .build();
        return retrofit;
    }

 public static VuAPIServices geVuAPIServices() {
        VuAPIServices vuAPIServices = getClient().create(VuAPIServices.class);
        return vuAPIServices;
    }

}

Activity code below

    public AuthenticationVO createRequest(){
        customLoader.show();
      AuthenticationVO authenticationVO = new AuthenticationVO ();
          authenticationVO.setMobileNumber(mobileNumber);
        return authenticationVO;

    }
    public void saveMobile(AuthenticationVO authenticationVO){

        Call<ResponseAPI> responseAPICall = ApiClient.geVuAPIServices().saveMobile (authenticationVO);
        responseAPICall.enqueue(new Callback<ResponseAPI>() {
            @Override
            public void onResponse(Call<ResponseAPI> call, retrofit2.Response<ResponseAPI> response) {
                customLoader.dismiss();
                if (response.isSuccessful()) {
                    Log.d("response", "code = " + response.code());
                    Log.d("response", "code = " + response.body());

//                    sessionManager.setLogin(true);
//                    sessionManager.setLoginMobile(mobileNumber);
//                    Intent home = new Intent(getApplicationContext(), VU_OTPHandler.class);
//                    home.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
//                    startActivity(home);
//                    finish();
                } else {
                    Log.i("onEmptyResponse", "Returned empty response");//Toast.makeText(getContext(),"Nothing returned",Toast.LENGTH_LONG).show();
         }
                Toast.makeText(VuLogin.this, "saved successfully", Toast.LENGTH_LONG).show();
            }
            @Override
            public void onFailure(Call<ResponseAPI> call, Throwable t) {
                Toast.makeText(VuLogin.this, "Request Failed "+t.getLocalizedMessage(), Toast.LENGTH_LONG).show();

            }
        });

Postman images

image 1

This is the controller below on server side i have written

 @PostMapping(path = ENDPOINT_MOBILE_OTP)
    public AuthenticationVO signInWithOTP(@Valid @RequestBody AuthenticationVO authenticationVO){
        System.out.println("login request is:-"+authenticationVO.toString());
        try {
        if (authenticationVO != null && authenticationVO.getMobileNumber()!=null) {
            MultitenantUtility.request = httpRequest;
            String tenantId = multitenantUtility.resolveCurrentTenantIdentifier();
            if (tenantId != null) {
                multitenantUtility.setCurrentTenant(tenantId);
                authenticationVO = userService.checkLoginCredentialsWithOTP(authenticationVO);
            } else {
                System.out.println("request body is empty");
                //throw new DMPBadRequestException("Request body is empty");
            }
            }
        else {
            System.out.println("Mobile Number is mandatory");
            //throw new DMPBadRequestException("Request body is empty");
        }
        }
        catch(Exception e) 
        {
            System.out.println("Excepton "+e);
        }
        finally
        {
            multitenantUtility.clearThreadLocal();
            LOGGER.info("authenticateUser - before returning");
        }
        
        
        return authenticationVO;
    }

Please guys help me on this issue. several days i have spent on trying to make it work many methods i tried but nothing worked. Please help me know what i am missing. Thanks in advance



Solution 1:[1]

Try this...

Replace below line

Call<ResponseAPI> saveMobile(@Body AuthenticationVO authenticationVO);

with

Call<ResponseAPI> saveMobile(@Body RequestBody jsonObject);

Now at below line also need to change

        Call<ResponseAPI> responseAPICall = ApiClient.geVuAPIServices().saveMobile (authenticationVO);

with

try {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("mobileNumber", 0123456789);
        RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), (jsonObject.toString()));

    }catch (Exception e){
        e.printStackTrace();
    }
  Call<ResponseAPI> responseAPICall = ApiClient.geVuAPIServices().saveMobile (body);
  //now continue as your code
  responseAPICall.enque.....

Also try to change retrofit client with this

public static Retrofit getClient(String baseUrl) {

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

    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient client = new   OkHttpClient.Builder().addInterceptor(interceptor).build();

    retrofit = new Retrofit.Builder()
            .baseUrl(baseUrl) //if all api base url is same only add here. If not same then add url as string in “getClient()” method and then pass that here
            .addConverterFactory(GsonConverterFactory.create(gson))
            .client(client)
            .build();
    return retrofit;
}

Hope this will work

Solution 2:[2]

Use:

        @RequestMapping(
                value = "/",
                method = RequestMethod.POST,
                produces = "application/json"
        )

Instead of @PostMapping("/")

With that, it will work fine

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Nensi Kasundra