Okay this is ridiculous: (or probably my design is :)
Here are the URLs that we are using:
/{projectName}/{wallName} - GET only: fetch all win conditions posted to the all
/{projectName}/WinCondition - POST a new Win Condition
/{projectName}/WinCondition/{id} - GET, PUT & DELETE
Now the funny part:
If the code is ordered as above the call POST: /myProject/WinCondition gets routed to the first route with wallName! And thus get a 405.
If I shift the /{projectName}/{wallName} to the bottom then it gets routed correctly!
Now here's what I know:
The default routing mode in Restlet
is MODE_FIRST_MATCH. I set that to
MODE_BEST_MATCH and the order of URLs
still matters! I am unable to access
the 'affinity' score to check what's
the problem/score. Matching mode is Template.MODE_EQUALS.
The question is then this: Do I have to be concerned with how I order the URLs in my java file???? That'll be scary, even from a maintenance point of view.
Any suggestions? Should I redesign my URLs?? But the 'structure' still tends to be the same leading to the same problem
"/{projectName}/{wallName}" and "/{projectName}/WinCondition" will obtain the same score for both FIRST_MATCH and BEST_MATCH so it is still the first in the route list that wins.
But this is really a side effect that you shouldn't get yourself into generally speaking. The problem is that it looks like you propose two routes to two different resource classes for the same URIs (such as "/myProject/WindCondition").
You should really consider redesigning your URIs to prevent such conflict. Here is a suggestion:
/{projectName}/walls/{wallName}
/{projectName}/winCondition
/{projectName}/winCondition/{id]
Otherwise, if relying on routes order scares you, it is possible to customize the default routing logic to take into account the target method for the scoring.
Related
what is the technical drawback of deleting a row on a GET method call in REST i know that it is not a standard way of doing but will there be having any issues ?
The technical drawback is that indexers (think Google) come along and GET all of the links that they can find, just to see what's there. General purpose components that see a link to your thing might do a GET on it as a way of pre-caching the results in case the client wants them.
Fielding, writing in 2002
HTTP does not attempt to require the results of a GET to be safe. What
it does is require that the semantics of the operation be safe, and
therefore it is a fault of the implementation, not the interface
or the user of that interface, if anything happens as a result that
causes loss of property (money, BTW, is considered property for the
sake of this definition)
I try to figure out the best solution for a use case I'm working on. However, I'd appreciate getting some architectural advice from you guys.
I have a use case where the frontend should display a list of users assigned to a task and a list of users who are not assigned but able to be assigned to the same task.
I don't know what the better solution is:
have one backend call which collects both lists of users and sends them
back to the frontend within a new data class containing both lists.
have two backend calls which collect one of the two lists and send them
back separately.
The first solution's pro is the single backend call whereas the second solution's pro is the reusability of the separate methods in the backend.
Any advice on which solution to prefer and why?
Is there any pattern or standard I should get familiar with?
When I stumble across the requirement to get data from a server I start with doing just a single call for, more or less (depends on the problem domain), a single feature (which I would call your task-user-list).
This approach saves implementation complexity on the client's side and saves protocol overhead for transactions (TCP header, etc.).
If performance analysis shows that the call is too slow because it requests too much data (user experience suffers) then I would go with your 2nd solution.
Summed up I would start with 1st approach. Optimize (go with more complex solution) when it's necessary.
I'd prefer the two calls because of the reusability. Maybe one day you need add a third list of users for one case and then you'd need to change the method if you would only use one method. But then there may be other use cases which only required the two lists but not the three, so you would need to change code there as well. Also you would need to change all your testing methods. If your project gets bigger this makes your project hard to update or fix. Also all the modifications increase the chances of introducing new bugs as well.
Seeing the methods callable by the frontend of the backend like an interface helps.
In general an interface should be open for extension but closed on what the methods return and require. As otherwise a slight modification leads to various more modifications.
I'm developing a REST API using Restlet.
So far everything has been working just fine. However, I now encountered an issue with the Router mapping of URL to ServerResource.
I've got the following scenario:
GET /car returns a list of all cars
GET /car/{id} returns details about the car with id 1
GET /car/advancedsearch?param1=test should run a search across all cars with some parameters
The first two calls work without any problems. If I try to hit the third call though, the Restlet Router somehow maps it to the second one instead. How can I tell Restlet to instead use the third case?
My mapping is defined as follows:
router.attach("/car", CarListResource.class);
router.attach("/car/{id}", CarResource.class);
router.attach("/car/advancedsearch", CarSearchResource.class);
CarSearchResource is never invoked, but rather the request ends up in CarResource.
The router's default matching mode is set to Template.MODE_EQUALS, so that can't be causing it.
Does anyone have any further suggestions how I could fix it?
Please don't suggest to use /car with the parameters instead, as there's already another kind of search in place on that level. Also, I'm not in control of the API structure, so it has to remain as it is.
you need to add .setMatchingQuery(true); to that rout in order it to recognize that it is with a query at the end of it.
Router router = (Router) super.createInboundRoot();
TemplateRoute route1 = router.attach("/car/advancedsearch?{query_params}", MyResource.class);
route1.setMatchingQuery(true);
return router;
Mind that this pattern is with the exact specific order that you have determined in the route i.e. advancedsearch comes first and query_params comes after
I was able to solve this by simply reordering the attach statements:
router.attach("/car/advancedsearch", CarSearchResource.class);
router.attach("/car", CarListResource.class);
router.attach("/car/{id}", CarResource.class);
Particularly, what are all the dots and numbers at the end for.
Here is an example:
https://www.google.com/search?site=&tbm=isch&source=hp&biw=1366&bih=673&q=kale&oq=kale&gs_l=img.3..0l10.403.1120.0.1352.4.4.0.0.0.0.407.543.0j1j4-1.2.0....0...1ac.1.32.img..2.2.542.vC-f2Kfx-2E
It is a GET variables value, but why such a strange un-human readable syntax?
I assume they are using PHP or Java on the back-end.
What you are seeing is internal computer data, not exactly intended for normal human consumption, but there for a good reason. Also perhaps you are thinking, why would anyone want these ugly internal details displayed on the average user's screen?
When HTTP was invented the thought was that GET requests should be stateful, in other words, if I copy a URI from my browser and email it to you, and you browse to it, then you should see exactly what I saw. To make this work the GET data needed to be in the URI and not hidden from view. Thus the dirty details you are seeing. Back in the day they were thinking of simple GET queries, for example: http://www.somedomain.com/Search?Find=FooBar
However, as software has evolved more data needs to be passed with GET requests and unfortunately it is all visible in the URI. (Note that this also becomes a minor security hole because the average user can see some of the internals of web page production and easily tamper with it.)
What is needed is a hidden data passing method for GET type queries to clean up URIs when it is not necessary for these details to be present. A proposal for such an improvement to HTTP is in the process of being considered. It would involve adding a new method to HTTP similar to GET but with hidden data passing like POST.
The HATEOAS principle "Clients make state transitions only through actions that are dynamically identified within hypermedia by the server"
Now I have a problem with the word dynamically, though I guess it's the single most important word there.
If I change one of my parameters from say optional to mandatory in the API, I HAVE to fix my client else the request would fail.
In short, all HATEOAS does is give the server side developer extreme liberty to change the API at will, at the cost of all clients using his/her API.
Am I right in saying this, or am I missing something like versioning or maybe some other media-type than JSON which the server has to adopt?
Any time you change a parameter from optional to mandatory in an API, you will break consumers of that API. That it is a REST API that follows HATEOAS principles does not change this in any way. Instead, if you wish to maintain compatibility you should avoid making such changes; ensure that any call made or message sent by a client written against the old API will continue to function as expected.
On the other hand, it is also a good idea to not write clients to expect the set of returned elements to always be identical. They should be able to ignore additional information given by a server if the server chooses to provide it. Again, this is just good API design.
HATEOAS isn't the problem. Excessively rigid API expectations are the problem. HATEOAS is just part of the solution to the problem (as it potentially relieves clients from having to know vast amounts about the state model of the service, even if it doesn't necessarily make it straight-forward).
Donal Fellows has a good answer, but there's another side to the same coin. The HATEOAS principle doesn't have anything to say itself about the format of your messages (other parts of REST do); instead, it means essentially that the client should not try to know which URI's to act upon out of band. Instead, the server should tell the client which URI's are of interest via hyperlinks (or forms/templates which construct hyperlinks). How it works:
The client starts at state 0.
The client requests a well-known resource.
The server's response moves the client to a new state N. There may be multiple states achievable at this point depending on the response code and payload.
The response includes links (or forms/templates) which tell the client, in band, the set of potential next states.
The client selects one of the potential next states by issuing a method on a URI.
Repeat 3 through 5 to states N+1 and beyond until the client's application needs are met.
In this fashion, the server is free to change the URI that moves the client from state N to state N+1 without breaking the client.
It seems to me that you misunderstood the quoted principle. Your question suggests that you think about the resources and that they could be "dynamically" defined. Like a mandatory property added to certain resource type at the application runtime. This is not what the principle says and this was correctly pointed out in other answers. The quoted principle says that the actions within the hypermedia should be dynamically identified.
The actions available for a given resource may change in time (e.g. because someone added/removed a relationship in the meantime) and there may be different actions available for the same resource but for different users (e.g. because users have different authorization levels). The idea of HATEOAS is that clients should not have any assumptions about actions available for certain resource at any given time. The client should identify available actions each time it reads that resource.
Edit: The below paragraph may be wrong. See the comments for discussion about it.
On the other hand clients may have expectation for the data available in the resource. Like that a book resource must have a title and that it there may be links to the book's author or authors. There is no way of avoiding the coupling introduced by these assumptions but both service providers and clients should use backward-compatibility and versioning techniques to deal with it.