I'm currently working on a small REST web service using spring-data-rest using :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
I followed the following guide: https://spring.io/guides/gs/accessing-mongodb-data-rest/ and it's working really fine.
I add some annotation on my Person.class, in order to validate the object during a POST request (like @NonNull and so on) like this :
public class Person {
@Id
private String id;
@NonNull
private String firstName;
@NonNull
private String lastName;
private Integer age;
}
But now I want to do a PATCH request to update my object (by doing a request curl -X PATCH http://localhost:8080/people/598c2a80d8425fae64161cc4 -d '{"age":23}').
It's also working fine, but I want to prevent the update on some fields, people shouldn't be allowed to update firstName and lastName for example.
Is there some way to do it easily with an annotation? Or do I have to do a custom validation for every PATCH (or PUT) request? I don't like that solution because I would have to do it for every entity of my model.
I hope I clearly exposed my problem, if it's not clear, feel free to ask me more questions.
Thanks for your help.
You could use:
@Column(updatable = false)
@NonNull
private String firstName;
This won't throw errors but will avoid the field from being updated.
You could override the specific PATCH endpoint and retain only the allowed fields
@PatchMapping("/persons/{id}")
HttpEntity<?> patchPerson(@PathVariable("id") Person person,
@RequestBody final ObjectNode patch,
PersistentEntityResourceAssembler assembler) {
List<String> allowedFields = List.of("age");
ObjectNode validPatch = patch.retain(allowedFields);
Person patchedPerson = jsonPatcher.merge(validPatch, person);
Person entity = personRepository.save(patchedPerson);
PersistentEntityResource resource = assembler.toFullResource(entity);
return ResponseEntity.accepted().body(resource);
}
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.data.rest.webmvc.json.DomainObjectReader;
import org.springframework.data.rest.webmvc.mapping.Associations;
import org.springframework.stereotype.Component;
/**
* Utility class mainly for applying patches to domain objects.
*/
@Component
public class JsonPatcher {
private final DomainObjectReader domainObjectReader;
private final ObjectMapper objectMapper;
@Autowired
public JsonPatcher(PersistentEntities persistentEntities, Associations associations, ObjectMapper objectMapper) {
this.domainObjectReader = new DomainObjectReader(persistentEntities, associations);
this.objectMapper = objectMapper;
}
/*
Almost the same exact implementation used in {@link org.springframework.data.rest.webmvc.config.JsonPatchHandler}
to merge JSON documents for Spring Data REST. It's copied here because the patch code that Spring uses was made
internal to the framework.
*/
public <T> T merge(ObjectNode patch, T target) {
return domainObjectReader.merge(patch, target, objectMapper);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With