Spring Data Rest custom controller with patch method - how to merge resource with entity
Asked Answered
E

1

7

By default when we have a repository with save method exposed we can do a PATCH request. Then Spring Data REST retrieves the original object from the database and apply changes to entity and then saves it for us (inside JsonPatchHandler class). This allows us to do the following request for class

class Address {
     Long id;
     String street;
     Long houseNumber;
}

PATCH /api/addresses/1 with body

{ houseNumber: 123 }

And only this one field will be changed.

Now having custom controller we would like to in the update method receive the whole object (after HATEOAS merged it with the original object from the DB)

@RepositoryRestController
@ExposesResourceFor(Address.class)
@ResponseBody
@RequestMapping("/addresses")
public class AdddressController {

    @PatchMapping("/{addressId}")
    public Resource<Address> update(@RequestBody Resource<Address> addressResource, @PathVariable Long addressId) {
        Address address= addressResource.getContent();
        // .... some logic
        address = addressRepository.save(address);
        return new Resource<>(address);
    }
}

Unfortunately in the place where I would do some logic I get the Address with null fields instead of the merged object.

Is it possible to plug the custom controller in the Spring Data REST stack so that when patching the request it will merge it for me (as it does for normal repositories)?

edit: I would like to find a solution that works transparently both with PATCH(content-type:application/json-patch+json) and PATCH(content-type: application/hal+json)

Edington answered 31/5, 2017 at 13:13 Comment(4)
I answered a similar question here - #33289170Heiskell
Possible duplicate of Custom Spring MVC HTTP Patch requests with Spring Data Rest functionalityHeiskell
indeed the question is similar, nevertheless I would like to find a solution that works transparently both with PATCH(content-type:application/json-patch+json) and PATCH(content-type: application/hal+json) - the one proposed by you can only work with the json-patchKwabena
You can look at org.springframework.data.rest.webmvc.config.JsonPatchHandler#apply to get an idea how spring-data-rest does it. Also org.springframework.data.rest.webmvc.RepositoryEntityController#patchItemResource is worth a look .Heiskell
E
2

After browsing the Spring sources I haven't found a reasonable solution. As a result I've created issue in their - JIRA

For the moment the only reasonable workaround is following - create custom controller that has PersitentEntityResource as a parameter and has both {id} and {repository} placeholders in its path i.e.

@PatchMapping("/addresses/{id}/{repository}")
public Resource<Address> update(PersistentEntityResource addressResource) {
    ...
}

which makes the invocation endpoint /addresses/123/addresses

Edington answered 6/6, 2017 at 15:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.