raptor123
raptor123

Reputation: 185

org.springframework.http.converter.HttpMessageNotReadableException when sending a POST request

I have a Spring application with the following controller:

   @RestController
   @RequestMapping("/app") 
   public class RegisterRestController {
   @Autowired
    UserRepository userRepository;

   @Autowired
   PasswordEncoder passwordEncoder;

   @Autowired
   UserService userService;


   @RequestMapping( value="/loginuser", method =RequestMethod.POST,produces="application/json")
    public String loginUser(@RequestBody String requestBody) {
    System.out.println("inside");
    JSONObject responseJsonObject = new JSONObject();
    String phonenumber;
    String password;
    try{
        JSONObject object = new JSONObject(requestBody);
        phonenumber = object.getString("phonenumber");
        password = object.getString("password");
        User user = userService.findByNumber(phonenumber);
        String sha256Password = passwordEncoder.encode(password);
        if(sha256Password.equals(user.getPassword())){
            responseJsonObject.put("response", "Login Successful");
        }
        else {
            responseJsonObject.put("repsonse", "Login failed");
        }
    }
    catch (Exception e){
        e.printStackTrace();
        try {
            responseJsonObject.put("response", "Invalid Credentials");
        } catch (JSONException e1) {
            e1.printStackTrace();
        }

    }
    return responseJsonObject.toString();
}

However, when I send a POST request from Postman containing :

    {
      "phonenumber":"9123456789",
      "password":"password"
  }

I get the following response:

    {
   "timestamp": 1456043810789,
   "status": 400,
    "error": "Bad Request",
    "exception":      "org.springframework.http.converter.HttpMessageNotReadableException",
    "message": "Could not read JSON: Can not deserialize instance of   java.lang.String out of START_OBJECT token\n at [Source: java.io.PushbackInputStream@eaa3acb; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: java.io.PushbackInputStream@eaa3acb; line: 1, column: 1]",
    "path": "/app/loginuser"
}

Also, I was experimenting with Spring Security as well. The server does not show any error and the controller does not seem to receive the request as "inside" is not being printed. I am trying to get acquainted with Spring, however I could not find the reason for such an error. I would be grateful for any help. Thanks in advance

Upvotes: 12

Views: 77895

Answers (3)

Abhishek Tiwari
Abhishek Tiwari

Reputation: 1

one of the reason apart of mentioned above could be, the type mismatch of fields. in my case, field was declared UUID and i was sending it as string. Sending it as UUID solved my problem.

Upvotes: 0

uncle-tee
uncle-tee

Reputation: 356

The Jackson library will automatically convert to JSON using the constructors you have defined in the login User method. So you need not to convert to json. So this means that

{
    "phonenumber": "9123456789",
    "password": "password"
}

should be defined in your in your constructor. You should have defined an entity class that defines a loginUser.

  public class LoginUser{
    String phonenumber;
    String password;

    // define all other variables needed.

    public LoginUser(String phonenumber, String password){
        this.phonenumber = phonenumber ;
        this.password = password;
    }

    public LoginUser() {
        //you need a default contructor. As srequired by spring
    }

    //Define the gettters and settters

}

Then

 @RequestMapping( value="/loginuser", method = RequestMethod.POST,produces="application/json")
    public String loginUser(@RequestBody LoginUser requestBody) {
        System.out.println("inside");
        try{

        phonenumber = requestBody.getPhonenumber; // please define your getters and setters in the login class
        password = requestBody.getpassword;
        User user = userService.findByNumber(phonenumber);
        String sha256Password = passwordEncoder.encode(password);
        if(sha256Password.equals(user.getPassword())){
        responseJsonObject.put("response", "Login Successful");
        }
        else {
        responseJsonObject.put("repsonse", "Login failed");
        }
        }
        catch (Exception e){
        e.printStackTrace();
        try {
        responseJsonObject.put("response", "Invalid Credentials");
        } catch (JSONException e1) {
        e1.printStackTrace();
        }

        }
        return responseJsonObject.toString();
}

You can use postman to try now. Goodluck

Upvotes: 1

There are two problems in your code:

  1. You try to convert the JSON into an object inside the controller. This is already done by Spring. It receives the body of the request and tries to convert it into the Java class of the according parameter in the controller method.
  2. Your controller method expects a single string: @RequestBody String requestBody

And you are sending an object with two properties:

{
    "phonenumber": "9123456789",
    "password": "password"
}

Solution:

Create a class for the values you need to login :

public class Login {
    public String phonenumber;
    public String password;
    // you need a zero argument constructor
    // maybe you have to add getter and setters
}

Change your controller method so it expects an object of this type

@RequestBody Login requestBody

Upvotes: 9

Related Questions