Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error 400 Spring Json @RequestBody when doing post

Here are the classes involve.

public class UserAuthDto {

    private String username;

    private String password;

    private List<String> roles;

    private String tenantCode;

    public UserAuthDto(String username,
                           String password,
                           List<String> roles,
                           String tenantCode){
        this.username=username;
        this.password=password;
        this.roles=roles;
        this.tenantCode=tenantCode;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setRoles(List<String> roles) {
        this.roles = roles;
    }

    public void setTenantCode(String tenantCode) {
        this.tenantCode = tenantCode;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public List<String> getRoles() {
        return roles;
    }

    public String getTenantCode() {
        return tenantCode;
    }
}

Another DTO

public class UserAuthRequest {

    private UserAuthDto userAuthDto;

    public UserAuthRequest(UserAuthDto authDto){
        if(authDto == null){
            throw new IllegalArgumentException("User Authentication DTO Should Not be null");
        }
        this.userAuthDto = authDto;
    }
    public String getUsername(){
        return userAuthDto.getUsername();
    }

    public String getPassword(){
        return userAuthDto.getPassword();
    }

    public List<String> getRoles(){
        return  userAuthDto.getRoles();
    }

    public String getTenantCode(){
        return  userAuthDto.getTenantCode();
    }

    public void setUsername(String username) {
        this.userAuthDto.setUsername(username);
    }

    public void setPassword(String password) {
        this.userAuthDto.setPassword(password);
    }

    public void setRoles(List<String> roles) {
        this.userAuthDto.setRoles(roles);
    }

    public void setTenantCode(String tenantCode) {
        this.userAuthDto.setTenantCode(tenantCode);
    }
}

And here's the Controller that was processing the request.

@RequestMapping(value = "authenticate", method = RequestMethod.POST,consumes = "application/json",produces = "application/json")
    public UserAuthResponse authenticate(@RequestBody UserAuthRequest authRequest){
       //.
    }

However when I send this data

{"username": "test","password":"test","roles":null,"tenantCode":"test"}

I receive a 400 bad request. any idea why?

like image 775
user962206 Avatar asked Mar 18 '23 20:03

user962206


2 Answers

Spring uses Jackson to map the JSON in the request to Java objects to pass as arguments to your handler method.

Here are the JSON types. Here's how Jackson does JSON mappings:

  1. JSON objects map to Java Map or custom class objects
    • The keys of JSON object key-value pairs map to class instance fields
  2. JSON arrays map to Java arrays or Collection types (List, Set, etc.)
  3. JSON numbers map to Java numerical types (int, double, Long, etc. Both primitive and reference types)
  4. JSON strings map to Java String objects (or fields if the JSON string is a key)
  5. JSON null maps to Java null
  6. JSON false and true map to Java false and true.

You've provided the following JSON

{"username": "test","password":"test","roles":null,"tenantCode":"test"}

This is a JSON object, with 4 key-value pairs, where the keys are username, password, roles, and tenantCode. So you need a Java class with fields (or properties) with those names. You have such a class, UserAuthDto. That's what you should use as your parameter type.


You can enable logging by providing the appropriate slf4j and logback or log4j libraries on the classpath with an appropriate configuration for Spring's loggers.

like image 180
Sotirios Delimanolis Avatar answered Mar 20 '23 10:03

Sotirios Delimanolis


I struggled this morning with a similar problem. I got a 400 even when the object I was sending was correct. My class was something like this:

class myClass {
   AnalysisResult average; //AnalysisResult is a List<double>
   AnalysisResult worstCase;
   public MyClass(AnalysisResult average, AnalysisResult worstCase) {
      //initializations
   }
}

It was solved by adding a default constructor:

class myClass {
   AnalysisResult average; //AnotherClass is a List<double>
   AnalysisResult worstCase;
   public MyClass(AnalysisResult average, AnalysisResult worstCase) {
      //initializations
   }
   public MyClass() {}
}

It seems that, for some classes, jackson requires a default constructor

like image 43
JACH Avatar answered Mar 20 '23 09:03

JACH