• Post Reply Bookmark Topic Watch Topic
  • New Topic

RESTful query query #2: Executing a stored query  RSS feed

 
Bear Bibeault
Author and ninkuma
Marshal
Posts: 66207
151
IntelliJ IDE Java jQuery Mac Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK, assuming that the URL to create a query in a RESTful API is along the lines of a PUT to:

http://localhost/whatever/whichever/query/My+Magic+Query

with the representation of the query as XML in the request body.

To match the rest of the RESTful API, a GET to the same URl would return the saved query itself, not the results of running the query.

So, what should the HTTP method and URL to actually execute the query and return the results look like?

Perhaps a GET to something like:

http://localhost/whatever/whichever/result/My+Magic+Query

with parameter data in the query string?

Is there a best-practice approach?
 
Peer Reynders
Bartender
Posts: 2968
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you have a look at the original topic RESTful APIs: GETs with bodies? you'll see that the issue never came up because the query was POSTed to the "parent" resource. The "parent" resource generates a URI to the "child" resource and the results are retrieved from the "child" resource URI. So that lack of symmetry of the representations never came up. What would you get if you allowed a GET on the "parent" resource? Possibly a listing of the currently available "child" resources ("hypermedia as the engine of application state"). I doubt you would allow a PUT on either the "parent" or "child" resource.

This seems to be a standard pattern for more process oriented interactions where the "PUT" representation doesn't match the "GET" representation.
 
Bear Bibeault
Author and ninkuma
Marshal
Posts: 66207
151
IntelliJ IDE Java jQuery Mac Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK, this is becoming a bit clearer. I've just got some lingering questions about the "two-phase" execution in our environment.

For our system, queries are being considered "first class" data model items. Clients will create named, persistent items that represents queries they'll want to repeatedly run with various parameterized values -- I guess you could think of them as persisted representations of prepared statements.

Clients will want to be able to create, delete, fetch, and modify the query definition ad nauseam.

For this I've set up the example URI:

http://localhost/whatever/whichever/query/My+Magic+Query

where PUT is used to create/update the query, GET is used to fetch its representation, and DELETE to remove it from the data model (just like all the other persisted items in the data model).

So, what you are saying is that a POST to this URI, with the parameterized values, would create a temporary child resource that represents the result (returned via the Location header) which could then be fetched with a GET to that child resource.

Question: in such a scenario, would it be improper to return the results directly as the response to the POST? It's unlikely that the clients would store a child result URI for later or repeated use, so I'm not sure there's much utility in creating the temporary resource unless not doing so violates an expected or best-practice RESTful precept.

Can you comment on that?



 
Peer Reynders
Bartender
Posts: 2968
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Bear Bibeault wrote:
Question: in such a scenario, would it be improper to return the results directly as the response to the POST?

You should not return the result. The creation of the child resource is the parent's action and the result of the operation is the URI to the created resource.

By trying to return the result immediately you are giving up some wiggle room. Some queries and processes can take a long time to complete. The child URI may be available immediately but when accessed it may give you the "still working on it" representation. For cache-ability concerns a "good resource" doesn't change all that often. If you were to issue the query every time somebody GETs the URI the representation isn't cache-able.

Maybe your query result should include a lifetime property so that the server is free to delete it once its lifetime expires (for one-off queries). Or a "result expiry" property (leading to a Cache-Control HTTP Header enabling caching down the line) making sure that a GET will only refresh the result if the current "result has expired" (for re-usable queries).
 
Bear Bibeault
Author and ninkuma
Marshal
Posts: 66207
151
IntelliJ IDE Java jQuery Mac Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Peer Reynders wrote:By trying to return the result immediately you are giving up some wiggle room. ... the representation isn't cache-able.

OK, I've got that. Though it's unlikely that cachability will be an issue as it is unlikely that a client will repeat the same query with the same parameters within a timeframe that we'd want to keep the result around for. Are there other benefits?

I'm imagining clients that hem-and-haw over having to do the subsequent GET rather than just receiving the results directly in the POST response.

Would it be deemed acceptable to have this a client-defined property: choose to receive direct results or a GET-able URI?

Some queries and processes can take a long time to complete.

This is a very good point. We haven't really designed the back-end query architecture yet, and I don;t think anyone is yet anticipating such asynchronous behavior, but it's something we did end up having to do at my previous job. I can see how the child-resource solution fits into that nicely.
 
Peer Reynders
Bartender
Posts: 2968
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Bear Bibeault wrote:Would it be deemed acceptable to have this a client-defined property: choose to receive direct results or a GET-able URI?


Given the uniform interface constraint of Resource-Oriented Architecture, POST is used by "factory resources" as the factory method. POST is the only non-idempotent method of the bunch, and creating child resources without a URI is a non-idempotent operation. Retrieving query results should be an idempotent operation (i.e. GET). (Sample Chapter 4 The Resource-Oriented Architecture)

However:
RESTful Web Services: Chapter 8 REST and ROA Practices
Overloading POST (p.220) wrote: ...
This is how most web applications work. XML-RPC and SOAP/WSDL web services also run over overloaded POST. I strongly discourage the use of overloaded POST, because it ruins the uniform interface. If you're tempted to expose complex objects or processes through overloaded POST, try giving objects or processes their own URIs, and exposing them as resources. I show several examples of this in "Resource Design" later in this chapter.
There are two noncontroversial uses for overloaded POST. The first is to simulate HTTP's uniform interface for clients like web browsers that don't support PUT or DELETE. The second is to work around limits of the maximum length of a URI. The HTTP standard specifies no limit on how long a URI can get, but many clients and servers impose their own limits: Apache won't respond to requests for URI's longer than 8KB. If a client can't make a GET request to http://www.example.com/numbers/11111111 because of URI length restrictions (imagine a million more ones there if you like), it can make a POST request to http://www.example.com/numbers?_method=GET and put "11111111" in the entity body.
...
A rule of thumb: if you're using POST, and never expose GET and POST on the same URI, you're probably not exposing resources at all. You've got an RPC-style service.
...
The principles of REST and the ROA are not arbitrary restrictions. They're simplifying assumptions that give advantages to resource-oriented services over the competition. RESTful resource-oriented services are simpler, easier to use, more interoperable, and easier to consume than RPC-style services.


Now lets be clear here. The assumption is simply that the URI does not fit. Also remember the addressability issue. While http://www.example.com/documents/conference?Title=RESTful and http://www.example.com/documents/conference?FullText=SOAP+XML%2FRPC may be processed by the same "Jersey resource" at http://www.example.com/documents, the REST architecture views them as two distinct resources that you can link to. So this exception doesn't give license to now change your query format representation, it expects you to place the remainder of the URI (e.g. conference?FullText=SOAP+XML%2FRPC) into the request body. It is also expected that the "Jersey resource" at http://www.example.com/documents can respond to real GET requests for less voluminous queries, so that the overloaded POST is only used in exceptional cases.
 
Peer Reynders
Bartender
Posts: 2968
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Bear Bibeault wrote:I'm imagining clients that hem-and-haw over having to do the subsequent GET rather than just receiving the results directly in the POST response.

If I had to explain this to Java programmers I would point out that they probably have no problem in Java with the fact that the query results would be returned in a container object. After general agreement I would then point out that in fact the object itself isn't returned - what is returned is a reference to the container object. You still have to access the container object itself to get at the query result data.

So the factory resource is returning a reference (URI) and you access (GET) the container resource to get the goods (the representation).
 
Bear Bibeault
Author and ninkuma
Marshal
Posts: 66207
151
IntelliJ IDE Java jQuery Mac Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Peer, this is all invaluable information. Thanks! Digesting now...
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!