【问题标题】:Invalid property `xyz` of bean class[java.util.ArrayList]: Bean property 'xyz' is not readable or has an invalid getter methodbean 类 [java.util.ArrayList] 的无效属性“xyz”:bean 属性“xyz”不可读或具有无效的 getter 方法
【发布时间】:2019-12-13 10:00:17
【问题描述】:

我是 Spring Boot 的新手。我在使用基于 javax 的验证时遇到问题。 控制器需要来自 POST 端点的 json obj 列表。在 JSON 请求 json 数组中, 如果 enginename 为空,我会得到正确的 400 错误。但是,当engine.typeengine.name 为 null,它会抛出 500 异常并显示错误消息:

Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'engine' of bean class 
[java.util.ArrayList]: Bean property 'engine' is not readable or has an invalid 
getter method: Does the return type of the getter match the parameter type of 
the setter?

Controller.java

@RestController
@Validated
public class CarController {
  @PostMapping(path = "/cars")
  public ResponseEntity<PostModelResponse> createModel(
          @Valid @RequestBody ArrayList<Car> cars)
          throws JSONException, ConstraintViolationException {
          ...
      return new ResponseEntity<>(response, HttpStatus.CREATED);
  }
}

汽车.java

class Car {
  @NotNull
  @Valid
  private Engine engine;

  @NotNull
  private String name;

  Cars(Engine engine, String name) {
    this.engine = engine;
    this.name = name;
  }

  public String getName(){ return name; }
  public void setName(String name) { this.name = name;}
  public Engine getEngine() { return engine; }
  public void setEngine(Engine engine){ this.engine = engine; }

}

Engine.java

class Engine {
  @NotNull
  private String type;
  @NotNull
  private String name;

  Engine(String type, String name) {
    this.type = type;
    this.name = name;
  }
  public String getType() { return type; }
  public void setType(String type) { this.type = type; }
  public String getName() { return name; }
  public void setName(String name) { this.name = name;}
}

CollectionValidator.java

public class CollectionValidator implements Validator {

    private final Validator validator;

    public CollectionValidator(LocalValidatorFactoryBean validator) {
        this.validator = validator;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return Collection.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        Collection col = (Collection) target;
        for ( Object obj : col ) {
            ValidationUtils.invokeValidator(validator, obj, errors);
        }
    }
}

ValidatorAdvice.java

@ControllerAdvice
public class ValidatorAdvice {

    @Autowired
    protected LocalValidatorFactoryBean validator;

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.initDirectFieldAccess();
        binder.addValidators(new CollectionValidator(validator));
    }
}

请求/响应:URL:http://localhost:8080/cars

  1. POST 正文:[{ “名称”:“沃尔沃”, “引擎” : { “类型”:“v3”, “名称”:“沃尔沃发动机” } }]

    响应:200(确定)

  2. POST 正文:[{ “引擎” : { “类型”:“v3”, “名称”:“沃尔沃发动机” } }]

    响应:400(应为 name 缺失)

  3. POST 正文:[{"name" : "Volvo"}]

    响应:400(应为 engine 缺失)

  4. POST 正文:[{ “名称”:“沃尔沃”, “引擎” : { “名称”:“沃尔沃发动机” } }]

    响应:500(我期待 400)错误:

    原因:org.springframework.beans.NotReadablePropertyException:bean 类的无效属性“引擎” [java.util.ArrayList]:Bean 属性“id”不可读或无效 getter 方法:getter 的返回类型是否与参数类型匹配 二传手?

在发布之前,我查看了其他 stackOverflow 结果。如果我接受Car 对象而不是ArrayList&lt;Car&gt;,一切正常

非常感谢任何帮助。

【问题讨论】:

    标签: java spring-boot bean-validation


    【解决方案1】:

    验证器作用于 bean,而不是列表;一种可能的解决方案是将列表包装在一个 bean 中,并在列表属性上使用 @Valid 注释:

    public class MyList<E> {
    
        @Valid
        private List<E> list;
    
        public List<E> getList() {
            return list;
        }
    
        public void setList(List<E> list) {
            this.list = list;
        }
    }
    

    并在控制器中验证:

    createModel(@Valid @RequestBody MyList<Car> cars)
    

    【讨论】:

    • 我也试过这个。但是,响应是一样的,它仍然抛出 500 异常
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 2020-11-27
    • 2021-06-16
    • 1970-01-01
    相关资源
    最近更新 更多