1

I am writing a controller that takes json array with hotels and validates it before saving. For example:

[
{   
    "name": "Hotel_1",
    "address": "address_1",
    "starsNumber": 3
},
{   
    "name": "Hotel_2",
    "address": "address_2",
    "starsNumber": 4
},
{   
    "name": "Hotel_2",
    "address": "address_2",
    "starsNumber": 3
}
]

At the beginning I used List<hotel> instead of WrapList<Hotel> as RequestBody, but It didn't work. So I tried to wrap it in wrap object as I read in this topic stackoverflow topic but It does not work as well and I always get empty list in my WrapList object. So the question is how to validate list of entities in elegant way.

If I use List instead of WrapList in my controller signature than my BindingResult never has errors instead of sending invalid data.

This is my model of hotel:

@Entity(name = "Hotel")
public class Hotel {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotBlank
    @Column(unique = true)
    private String name;

    private String address;

    @Range(min = 0, max = 5)
    private int starsNumber;

    @OneToMany(mappedBy = "hotel", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @Valid
    private List<Reservation> reservationList = new ArrayList<>();

    public Hotel() {
    }

    public Hotel(String name, String address, int starsNumber, ArrayList<Reservation> reservationList) {
        this.name = name;
        this.address = address;
        this.starsNumber = starsNumber;
        this.reservationList = reservationList;
    }


    public List<Reservation> getReservationList() {
        return reservationList;
    }

    public void setReservationList(List<Reservation> reservationList) {
        this.reservationList = reservationList;
    }

    @Override
    public String toString() {
        return String.format(
                "Hotel[id=%d, name='%s', address='%s', starts=%d]\"", id, name, address, starsNumber
        );
    }

    public void addReservation(Reservation reservation){
        reservationList.add(reservation);
        reservation.setHotel(this);
    }
}

This is my WrapList class:

class WrapList<E> implements List<E>{

@Valid
@NotEmpty
private List<E> list = new ArrayList<>();


public WrapList() {
}

public WrapList(@Valid List<E> hotelList) {
    this.list = hotelList;
}

public List<E> getList() {
    return list;
}

public void setList(List<E> list) {
    this.list = list;
}


@Override
public int size() {
    return list.size();
}

@Override
public boolean isEmpty() {
    return list.isEmpty();
}

@Override
public boolean contains(Object o) {
    return false;
}

@Override
public Iterator<E> iterator() {
    return list.iterator();
}

@Override
public Object[] toArray() {
    return list.toArray();
}

This is my rest controller:

@PostMapping("/create-many-test/")
    public ResponseEntity createManyTest(@Valid @RequestBody WrapList<Hotel> wrapHotelList, BindingResult bindingResult) {

        System.out.println(wrapHotelList.getList().toString());


        if (bindingResult.hasErrors()){

            return new ResponseEntity<>(bindingResult.getFieldErrors(), HttpStatus.BAD_REQUEST);

        }

        return new ResponseEntity<>(wrapHotelList.getList(), HttpStatus.CREATED);
    }
Przemek
  • 647
  • 2
  • 8
  • 25
  • Do you mean changing the signature of method to: public ResponseEntity createManyTest(@Valid @RequestBody List hotelList, , BindingResult bindingResult) ??? – Przemek May 30 '18 at 07:49
  • Well after chagning it as you said my BindingResult object has never errors. Do you know how to access the list of errors and send it to the client? – Przemek May 30 '18 at 08:10
  • Hi I got it wrong, it doesn't validates collections, you need to write a custom collection validator, see this https://stackoverflow.com/a/36790509/3295987 – Hemant Patel May 30 '18 at 08:56

0 Answers0