Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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)

like image 557
Paweł Avatar asked May 31 '17 13:05

Paweł


1 Answers

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

like image 103
Paweł Avatar answered Nov 06 '22 06:11

Paweł