brainmassage brainmassage - 4 months ago 29
Javascript Question

Bad request errror between spring boot and angularjs by a post request

I have two small projects, backend spring-boot side is responsible for providing the data, and angularjs frontend part is just displaying that data. I am trying to post a json from angular side and spring-boot side consumes and sends a respond.

This is horse racing data in json; "jokey" means rider and contains rider information:

var list = {"horses": [{"horseId":45942,"horseName":"Decolte","raceId":8449,"kilo":61.0,"jokey":{"name":"AYETULLAH DEMİR","raceNumber":41,"first":1,"second":4,"third":0,"fourth":1},"ekuriId":0},
{"horseId":27520,"horseName":"Busıness Man","raceId":8449,"kilo":57.0,"jokey":{"name":"CİVAN ÖZŞAHİN","raceNumber":190,"first":7,"second":15,"third":18,"fourth":12},"ekuriId":0},
{"horseId":55856,"horseName":"Erselçuk","raceId":8449,"kilo":57.0,"jokey":{"name":"NAİL EREN","raceNumber":64,"first":2,"second":0,"third":4,"fourth":2},"ekuriId":0},
{"horseId":52940,"horseName":"Haşim Ağa","raceId":8449,"kilo":57.0,"jokey":{"name":"DOĞUKAN AYDOĞAN","raceNumber":380,"first":11,"second":18,"third":10,"fourth":24},"ekuriId":0},
{"horseId":53431,"horseName":"İhtiyar","raceId":8449,"kilo":57.0,"jokey":{"name":"CÜNEYİT GÖKÇE","raceNumber":598,"first":32,"second":52,"third":64,"fourth":65},"ekuriId":0},
{"horseId":51778,"horseName":"Urla Zamanı","raceId":8449,"kilo":57.0,"jokey":{"name":"ADEM ŞEN","raceNumber":280,"first":18,"second":25,"third":32,"fourth":32},"ekuriId":0},
{"horseId":51816,"horseName":"Wın Every Day","raceId":8449,"kilo":57.0,"jokey":{"name":"EMRE NALBANT","raceNumber":405,"first":19,"second":26,"third":36,"fourth":33},"ekuriId":0},
{"horseId":58650,"horseName":"Lıon Amed","raceId":8449,"kilo":52.0,"jokey":{"name":"CANER KARADEMİR","raceNumber":134,"first":7,"second":7,"third":8,"fourth":7},"ekuriId":0},
{"horseId":51239,"horseName":"Catch The Wınd","raceId":8449,"kilo":57.0,"jokey":{"name":"MÜSLÜM CANPOLAT","raceNumber":238,"first":5,"second":12,"third":12,"fourth":19},"ekuriId":0},
{"horseId":46263,"horseName":"Ian Tapp","raceId":8449,"kilo":58.0,"jokey":{"name":"ERDEM NUR TÜFEKÇİ","raceNumber":79,"first":3,"second":1,"third":4,"fourth":5},"ekuriId":0},
{"horseId":51647,"horseName":"Sılverado","raceId":8449,"kilo":57.0,"jokey":{"name":"ÜMİT DERYA ALTEKİN","raceNumber":1185,"first":48,"second":53,"third":64,"fourth":84},"ekuriId":0},
{"horseId":57231,"horseName":"Junıor Duru","raceId":8449,"kilo":58.0,"jokey":{"name":"BEDRİ TEPE","raceNumber":716,"first":45,"second":55,"third":50,"fourth":67},"ekuriId":0}
]};


It was basically an array but somebody on stackoverflow told the data inside ajax request should be an object so I added "horses:" to the front. The json is manually added inside the code.

This is http request:

$http({
url: 'http://localhost:8080/horseHistory',
method: 'POST',
contentType: "application/json",
data: list.horses,
headers: {
"Content-Type": "application/json"
}
}).success(function(data) {
console.log(data);
});


On the backend I just want to see a working http connection so it is mostly empty. This is spring-boot function:

@RequestMapping(value = "/horseHistory", method = RequestMethod.POST )
public ResponseEntity<Void> getHorseHistory(@RequestBody HorseRaceModel[] horseRaces) throws IOException {

System.out.println(horseRaces[0]);

return null;
}


HorseRaceModel:

package ganyan;

public class HorseRaceModel {
int horseId;
String horseName;
int raceId;
double kilo;
JokeyModel jokey;
int ekuriId;

public HorseRaceModel(int horseId, String horseName, int raceId, double kilo, JokeyModel jokey, int ekuriId) {
this.horseId = horseId;
this.horseName = horseName;
this.raceId = raceId;
this.kilo = kilo;
this.jokey = jokey;
this.ekuriId = ekuriId;
}

public int getHorseId() {
return horseId;
}

public void setHorseId(int horseId) {
this.horseId = horseId;
}

public void setHorseName(String horseName) {
this.horseName = horseName;
}

public String getHorseName() {
return horseName;
}

public int getRaceId() {
return raceId;
}

public void setRaceId(int raceId) {
this.raceId = raceId;
}

public double getKilo() {
return kilo;
}

public void setKilo(double kilo) {
this.kilo = kilo;
}

public JokeyModel getJokey() {
return jokey;
}

public void setJokey(JokeyModel jokey) {
this.jokey = jokey;
}

public int getEkuriId() {
return ekuriId;
}

public void setEkuriId(int ekuriId) {
this.ekuriId = ekuriId;
}


}

JokeyModel:

public class JokeyModel {

private String name;
private int raceNumber;
private int first;
private int second;
private int third;
private int fourth;

public int getSecond() {
return second;
}

public void setSecond(int second) {
this.second = second;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getRaceNumber() {
return raceNumber;
}

public void setRaceNumber(int raceNumber) {
this.raceNumber = raceNumber;
}

public int getFirst() {
return first;
}

public void setFirst(int first) {
this.first = first;
}

public int getThird() {
return third;
}

public void setThird(int third) {
this.third = third;
}

public int getFourth() {
return fourth;
}

public void setFourth(int fourth) {
this.fourth = fourth;
}


}

The error from Chrome console:

Failed to load resource: the server responded with a status of 400 (Bad Request) http://localhost:8080/horseHistory


The error from Java console:

nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.HashMap out of START_ARRAY token

Answer

I'm not familiar with Spring Boot and I don't know why you have been told to post a JSON object instead of a JSON array, but I see that you are not doing it coherently.

You wrapped your JSON array in a JSON object called list, but by specifying data: list.horses you are still only passing the embedded JSON array. Since you want to send the whole JSON object, you should specify data: list instead.

Furthermore, I think that you need to define the wrapper model on the server side, which may be some class like this:

public class ListModel {
    private List<HorseRaceModel> horses;

    public List<HorseRaceModel> getHorses() {
            return horses;
    }

    public void setHorses(List<HorseRaceModel> horses) {
        this.horses = horses;
    }
}

Finally, the method consuming the post should be instructed to parse the request body into a ListModel. This means to modify the method to something like this:

@RequestMapping(value = "/horseHistory", method = RequestMethod.POST )
public ResponseEntity<Void> getHorseHistory(@RequestBody ListModel horseRaces) throws IOException {

    System.out.println(horseRaces.getHorses().get(0).getName());

    return null;
}

Side note: I also modified the code to print the name of the first horse instead of the object pointer that would be printed by System.out.println(horseRaces.getHorses().get(0));. You may want to print something else instead. You may also want to use better names for the wrapper object and model (instead of list and ListModel)

Note from comment: Your HorseRaceModel class does not have an empty constructor, you need to provide one for deserialization to work