简体   繁体   中英

@RequestBody not working on Rest service

I am developing a web application with AngularJS and WildFly using Spring also.

My problem is that I am going nuts because the annotation @requestBody appears to work wrong.

This is my service:

@ResponseBody
@RequestMapping(value = "/keyuser", method = RequestMethod.POST,
  consumes = "application/json")
public KeyProfileUserSummary updateEmployee(@RequestBody KeyProfileUserSummary keyUser) {
return null;
}

And this is are the members of my object KeyProfileUserSummary:

private Integer id;
private String login;
private String password;
private String firstname;
private String lastname;
private UserRole userRole;

I don't know what is going on but I have tested this service with other types of objects and it works perfectly, but when defining KeyProfileUserSummary it is not working, I get ERROR 400 BAD REQUEST. I have tested to set the @RequestBody to "Object" so at least I can see what is coming, and from my front end, I am getting the following:

{id=3, login=aa, password=a, firstname=Martin, lastname=Müller, userRole=ROLE_USER} 

UserRole is an Enum. Important to clearify that KeyProfileUserSummary is just a summary version of KeyProfileUser, but due to all the linked elements I get on the response, I decided to send this lighter class. Testing with KeyProfileUser worked perfectly, I get the JSON object on the Angular side and can send it back.

On the Angular side, I am not doing anything with the object. Just receive it on a list, and when pressing an edit button just send the element on the list back. This is the way I am sending it:

res = $http.post("url.../keyuser", user);

The thing is that I had everything working perfectly with KeyProfileUser, but as the database can get really huge and the reference are quite a lot, I decided to switch to this lighter class, but now I only get this ERROR 400 BAD REQUEST... And I am about to hang myself :P

Thanks for your help!

Ok so finally I found the solution.

In my KeyProfileUserSummary I only had one constructor that was taking a KeyProfileUser and set the attributes to the summary version:

public KeyProfileUserSummary(KeyProfileUser keyProfileUser) {
  this.id = keyProfileUser.getId();
  this.login = keyProfileUser.getLogin();
  this.password = keyProfileUser.getPassword();
  this.firstname = keyProfileUser.getPerson().getFirstname();
  this.lastname = keyProfileUser.getPerson().getLastname();
  this.userRole = keyProfileUser.getUserRole();
}

And apparently, setting a breakpoint in line 993 of the dispatchler servlet (thanks to @Clemens Eberwein for the tip) I realised that when parsing from a JSON object, the Jackson parser needs an empty constructor ! So adding it solved it and works perfectly.

Note: for KeyProfileUser, it was working perfectly as we had the annotation @Entity for hibernate, and therefore the empty constructor was automatically created.

Try this out.. might be useful for you..

$http({
    method: 'POST',
    url: 'http://localhost:8080/keyuser',
    data: user,
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }}).then(function(result) {
           console.log(result);
       }, function(error) {
           console.log(error);
       });

If I were to guess, jackson is failing in deserializing/serializing your object. Here is an util I made:

import java.io.IOException;
import java.nio.charset.Charset;

import org.springframework.http.MediaType;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

public class SerializeDeserializeUtil {

    public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(
            MediaType.APPLICATION_JSON.getType(),
            MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));

    public static byte[] convertObjectToJsonBytes(Object object)
            throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(Include.NON_NULL);

        return mapper.writeValueAsBytes(object);

    }

    public static <T> T deserializeObject(String jsonRepresentation,
            Class<T> clazz) throws JsonParseException, JsonMappingException,
            IOException {

        ObjectMapper mapper = new ObjectMapper();

        Object obj = mapper.readValue(jsonRepresentation.getBytes(), clazz);

        return clazz.cast(obj);
    }


    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static byte[] convertObjectToJsonBytesWithCustomSerializer(
            Object object, JsonSerializer serializer, Class clazz)
            throws IOException {

        ObjectMapper mapper = new ObjectMapper();

        SimpleModule sm = new SimpleModule();
        sm.addSerializer(clazz, serializer);

        mapper.registerModule(sm);
        mapper.setSerializationInclusion(Include.NON_NULL);

        return mapper.writeValueAsBytes(object);

    }

}

Try creating a test just to serialize and deserialize the objec. create a KeyProfileUserSummary object and try deserializing/serializing too see if jackson complains.

A more easier way is to enable DEBUG logging and checking the log file, by default you don't get to see this kind of errors

Hope it helps.

If you add DEBUG logging for "org.springframework.web" org.springframework.web.servlet.DispatcherServlet should give you detailed information what causes the "400 Bad Request" error.

Details about Wildfly logging configuration can be found here

Based on your KeyProfileUserSummary class i guess the problem is the UserRole object which ist just userRole=ROLE_USER in the example above. As it is an object it should be enclosd by curly braces and the property name must be set. eg something like

userRole = { name = "ROLE_USER"}

If it is an enum, this answer might be helpful

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM