1

Is there a way to tell MongoRepository to implement $addToSet when updating an array value during PATCH request?

I am using Spring data rest with HATEOAS and Mongodb, and the current implementation replaces the old array with the new array, where the desired functionality is to perform a union of both arrays and have that array stored in the Mongodb document.

While it should be possible to do that with custom implementation, Spring won't generate a rest url for the implementation and hence would require a lot of boilerplate for a rather small requirement. All responses appreciated.

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
user3848737
  • 45
  • 2
  • 5

1 Answers1

2

Spring Data REST is build on top of domain objects and the repository abstraction. So letting it work with a store specific implementation is out of its scope. I am assuming your core goal is to apply a PATCH request to your domain instance and that $addToSet is just the means to achieve that.

Since version 2.2 M1 of Spring Data REST we support the JSON Patch media type on PATCH request. So you can send the following document to the server:

[{ "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }]

Assuming c is the array your trying to manipulate, this would add foo and bar to it.

The other - more radical option is to actually deploy a manually implemented controller and hook it into the correct place in the URI space to manually interact with the repository.

Community
  • 1
  • 1
Oliver Drotbohm
  • 80,157
  • 18
  • 225
  • 211
  • @Olivier-gierke Thanks for your reply! I don't see 2.2 M1 available on maven. The latest is 2.1.1.RELEASE and on this version, the server throws a 405 upon sending it a similar document. Infact before your reply I was trying to implement a solution where a similar document is sent to the server and I use preHandle in an interceptor to process it. Do you believe it's a viable solution until 2.2 M1 is available? Thanks! – user3848737 Jul 18 '14 at 12:05
  • Milestones are available from the [Spring IO repositories](http://repo.spring.io/libs-milestone). – Oliver Drotbohm Jul 18 '14 at 12:23
  • @Olivier-gierke Got it, thanks! However I still get a 405 upon sending the document to the server using curl: `curl-i -X PATCH -H "Content-Type:application/json" -d '{"op": "add", "path": "/reminder/53c84d00b02ec66a1e328ccf/sendeeids","value":["dontreplace"]}' http://localhost:8080/` Only viable verbs seem to be GET, HEAD and OPTIONS. Am I doing something wrong here? – user3848737 Jul 18 '14 at 12:53
  • The media type you need to send is `application/json-patch+json`. – Oliver Drotbohm Jul 18 '14 at 12:54
  • @Olivier-gierke It still gave the same error. Then I changed the document and resource a bit as in the following curl : `curl -i -X PATCH -H "Content-Type:application/json-patch+json" -d '{"op": "add", "path": "/sendeeids","value":["dontreplace"]}' http://localhost:8080/reminder/53c84d00b02ec66a1e328ccf`. Now it doesn't give 405 but bad request, saying it couldn't read the object of the pojo(com.company.prod.pojo.Reminder) used to define the resource referred to by `http://localhost:8080/reminder/53c84d00b02ec66a1e328ccf` in the curl request. Is there an example/tutorial about this somewhere? – user3848737 Jul 18 '14 at 13:17
  • Can you gist the exception you get? – Oliver Drotbohm Jul 18 '14 at 13:19
  • I am working on a better error message currently. The error is caused by an invalid path actually. To append an item to the array, you need to use `/sendeeids/-` (see [the spec](http://tools.ietf.org/html/rfc6902#appendix-A.16) for details). – Oliver Drotbohm Jul 18 '14 at 17:24
  • @Olivier-gierke Since I need to add an element to an existing array, I am following this link : http://tools.ietf.org/html/rfc6902#appendix-A.2 . However, this throws the same error. Debugging shows it blows at line 107 in JsonPatchHandler, trying to get the list of operations, which I thinks shouldn't fail with the curl : `curl -i -X PATCH -H "Content-Type:application/json-patch+json" -d '{"op": "add", "path": "/sendeeids/1","value":"dontreplace"}' http://localhost:8080/reminder/3c84d00b02ec66a1e328ccf`. Thoughts? – user3848737 Jul 19 '14 at 03:41
  • @Olivier-gierke I am stuck with this since the weekend and can't go forward. Is there any test case in the code that shows this working or any sort of tutorial that I can compare my approach against? – user3848737 Jul 22 '14 at 19:30
  • @Olivier-gierke Resolved. Turns out that even though the there is a single operation to be sent to the server, it has to be included inside "[]". I have added a test for "add" operation in JsonPatchHandlerUnitTests class. Let me know if you want a pull request. – user3848737 Jul 23 '14 at 11:00
  • Good point. I'll tweak my answer accordingly. Thanks for accepting! :) – Oliver Drotbohm Jul 23 '14 at 13:32