0

So what I am having is a spring controller:

@Controller
@RequestMapping("/user")
public class UserController() {

    @RequestMapping(value = "/edit/{id}", method = RequestMethod.PUT)
    public @ResponseBody HTTPResponseDTO edit(@RequestBody String data, @PathVariable long id) {
        // marshall data String to User entity
        ObjectMapper mapper = new ObjectMapper();
        User marshaledUser = mapper.readValue(data, User.class);
        User databaseUser = session.get(id, User.class);
        //hibernate things to save
        ...
        // session.save(user);
    }

The data string is in the following json format:

{"name":"value1",
 "email":"value2",
 "note":"value3"}

The responseDTO is something simple looks like:

{"result":"success"}

When the client is passing in a data json, it will only pass in the value that is being edited, e.g.:

{"email":"value2"}

in this case, other non-supplied fields will be treated as null.

however "note" is a nullable field, and a user is allowed to clear the "note" field - in my current design, when it is doing so, it will be something like:

{"note":null}

QUESTION 1: So here is my dilemma: how can I tell if a user is on purpose to set this to null, or it is null only because it is not passed in from the data string?

QUESTION 2: When the controller is receiving the data String, I will have an entity coming from this data, I will then query database by id to get the existing User object. what is the best practice to merge these two objects? Looking for what fields exist in the marshaledUser and setting those to the databaseUser looks like lots of repetitive jobs:

if (marshaledUser.name != null) {
    databaseUser.name = marshaledUser.name;
}
if (marshaledUser.email != null) {
    databaseUser.email = marshaledUser.email;
}
if (marshaledUser.note != null) { // refer to question 1...
    databaseUser.note = marshaledUser.note;
}

An object can easiler have over 5 fields - 5 if statements of almost same thing looks not worth it.. What is the best practice to handle this?

jamesdeath123
  • 4,268
  • 11
  • 52
  • 93
  • Your code snippet gives no clue about how you parse the data. – holmis83 Nov 24 '14 at 18:16
  • @holmis83 not sure how that would help but I just updated the question to include the marshal feature - I am using org.codehaus.jackson.map.ObjectMapper to do the job. – jamesdeath123 Nov 24 '14 at 18:35
  • Related: http://stackoverflow.com/questions/8320993/jackson-what-happens-if-a-property-is-missing – holmis83 Nov 24 '14 at 18:43

2 Answers2

2

QUESTION 1: So here is my dilemma: how can I tell if a user is on purpose to set this to null, or it is null only because it is not passed in from the data string?

You can't. So, either change your approach and always pass a complete User (that's what I would do), instead of only a few fields, or unmarshall the JSON to a Map (or a JsonObject). If the key is present, but has a null value, then the value as been passed and is null. If the key is not present, then it hasn't been passed.

QUESTION 2: When the controller is receiving the data String, I will have an entity coming from this data, I will then query database by id to get the existing User object. what is the best practice to merge these two objects?

Same as question 1. It would be so much simpler if the client passed a complete User object instead of only a few fields. The method would simply look like

@RequestMapping(value = "/edit/{id}", method = RequestMethod.PUT)
public @ResponseBody HTTPResponseDTO edit(@RequestBody User user, @PathVariable long id)
    user.setId(id);
    session.merge(user);
}

Or at least, you would simply copy every field of the passed user to the persistent one, without caring if it has been sent or not.

Also, returning a HttpResponseDTO containing result = success is redundant. If the method completes normally, it will return with a 200 - OK HTTP status. If it doesn't, then you should return another HTTP status code.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
0

I think 1 approach is to read your target object from the database and covert it to json. Then merge your request json using a technique described here

Community
  • 1
  • 1
6ton
  • 4,174
  • 1
  • 22
  • 37