4

In Spring-Data-Rest an object's ID is the URI returned with the object. For example, if I have a User, it might have a URI like:

http://example.com/users/1

In an authentic REST api, this URI is the id of the object, you are not supposed to use just '1' as the id.

Give that, how do I search for all Orders that belong to that User?

http://example.com/orders/search/findByUser?user={{XXX}}

Specifically, what do I use for {{XXX}}?

I know I could do the opposite search:

http://example.com/users/1/orders

But in my case I need to search for matching jobs so I can add additional parameters which are also keys.

I can export /orders/search/findByUser by creating this function definition on OrderRepository:

List findByUser(User user);

and findByUser will be exported by Spring-Data-REST, but how do I specify the User as a GET parameter?

Again, I'm specifically looking for the pure REST solution, since the Spring Data Rest project is trying to encourage purity.

JBCP
  • 11,766
  • 6
  • 67
  • 107

3 Answers3

3

You might take a look at the Query annotation of Spring Data. It enables you to execute custom queries without the need of a custom controller.

Edit:

Query parameters are a good way to filter a resource by simple properties. As SDR serializes all complex types as relations, it is even clearer that filtering only applies to the remaining (simple) properties. If you have only one relation, you correctly mentioned the way of doing the 'inverse' search as you called it by using /users/1/orders.
If you want to search by multiple relations I suggest you define a seperate search (sub-)resource and perform the search by issuing a POST-request to this resource.
For example:

POST /orders/search
{
    "user": "http://example.org/users/1",
    ...
}

This way, SDR will correctly translate the URIs into entities. However, I think you will need to use a custom controller here but it should be possible to still use the Spring Data repository and provide the user and additional entities as parameter.

For further information, see the following SO-questions:

How to design RESTful search/filtering?
RESTful URL design for search

Edit2:

Addressing the point that using a POST for searching violates the REST spec:

REST was designed to be simple. One of the key advantages of REST is that you are not forced to do anything. You can adapt the spec until it fits your needs. Of course, this could mean that your API is less RESTful but you should consider if it is worth it to strictly stick to the spec if it introduces an unnecessary overhead for the consumers of your API.

Of course you can design the above the idea to fully meet the REST spec. This would involve creating a seperate search entity, persisting it to the database and later retrieve the result of the search with a call to a subresource like /result or something like that. However, the question is, if it is worth it.

In your concrete example, I would just require the client to parse the ID out of the link and provide it as query parameter. If you are scaling up your application later, you could introduce a feature like named searches and apply the above mentioned solution.

Community
  • 1
  • 1
Thomas Eizinger
  • 1,226
  • 12
  • 25
  • As far as i know, the @Query annotation can't translate from a url-id that SDR returns to the client into a database id – JBCP Jan 24 '15 at 03:13
  • Well, you cannot pass in the url directly as parameter but that would require to append the complete url as a parameter to the query string. That is not needed at all, as the meaning of the id is defined by the query key (?userid=XX). You will need to extract the id out of the url on the client side. Once you pass the id as a parameter to the query, you can execute any query you want. – Thomas Eizinger Jan 24 '15 at 15:16
  • Yes, i understand, but that is not 'pure REST'. In pure REST the url is the id, so the client should not need to parse it. I'm looking for the pure REST solution, since the Spring Data Rest project is trying to encourage purity. – JBCP Jan 24 '15 at 16:13
  • I have updated my answer, as I think I have now understood what you are trying to achieve. – Thomas Eizinger Jan 24 '15 at 23:13
  • Interesting solution, i will think about it. However, according to REST purity, POST should only be used to create documents, or is not "supposed" to be used for search. Honestly i think the real problem is that the HTTP spec did not consider that complex data would be necessary for GET requests – JBCP Jan 24 '15 at 23:16
  • I edited my answer again as the comment section did not provide enough space for it and I considered it as important enough to actually include it in the answer. – Thomas Eizinger Jan 24 '15 at 23:41
  • @JBCP It's called POST and not CREATE. The HTTP spec **explicitly** mentions the use case of sending data to a service. Furthermore: _The actual function performed by the POST method is determined by the server_ – a better oliver Jan 27 '15 at 10:02
0

If you use a controller, like it seems to be your case, you can pass it any parameter(s) you consider necessary. Take a look at this question:

Spring Data REST custom query integration

Community
  • 1
  • 1
Andres
  • 9,722
  • 4
  • 37
  • 57
  • A custom controller is one option, but I was hoping SDR had a built in solution. For example, you can construct custom queries in your OrderRepository like 'findByUser(User u)', and these queries will be exported by SDR and Spring HATEOAS, but I cannot figure out how to use them. – JBCP Jan 20 '15 at 20:37
0

See https://jira.spring.io/browse/DATAREST-502

Depending of your version of Spring Data, it would work as you want or not. By the way, I still think the POST should be an option too, it would be much cleaner.

JR Utily
  • 1,639
  • 1
  • 20
  • 34