I am currently working on a Hapi-FHIR project.
There I want to implement a collection of Questionnar Responses by Patient. The collection gives back all QuestionnaireResponses of a Patient with a given PatientId.
This works without problems but I also want to adhere to the REST Resource Naming Conventions.
So the search URL for my Collection shoud look something like
https://example.com/patient/{id}/questionnaireresponses.
Right now my search URL looks like this:
https://example.com/QuestionnaireResponse?patient={id}
I already tried to set my own search Url with #Path("/patient/{id}/questionnaireresponses") but HAPI-FHIR seems to ignore this.
I searched the HAPI-FHIR documentation already but I did not find anything related.
My question is where does the naming of the search urls happen in HAPI-FHIR and how can I change the name of a search url?
While I also find the FHIR naming and syntax choices a bit annoying, they're an integral part of the FHIR specification, not specific to Hapi. If you change them, your server won't be usable by a client that is expecting the standardized FHIR API. Which kind of defeats the point of using FHIR, no?
It might well be trivial to change the resource name in a Hapi server request (Patient to patient or patients), but since it doesn't really make that much sense, it might not be. So technically you might be forced to prehandle requests to support even that part of your syntax.
For the kind of hierarchical interrogation that you want, (patient/{id}/questionnaireresponses), things are more complicated even pure semantically, because there might be more than one relationship between two resource types. Even for your example, would patient/{id}/questionnaireresponses return just the responses where the patient is the subject, or also those where he is only the author? And how would you retrieve just those he has authored? FHIR is designed to be as explicit as possible to avoid different interpretations that can lead to wrong information being sent.
HapiFhir offers a mechanism for grouping two resources together.
Using compartments solved my problem.
Related
Suppose I have two models, Order and Customer. I've implemented an API that lets you filter on both:
/orders?status=fulfilled
/customers?city=Atlanta
But what if I want to search for orders in a fulfilled status, whose associated customer also lives in Atlanta? Is it RESTful to do something like /orders?status=fulfilled&customer.city=Atlanta? Or is there a canonical format for doing this sort of thing?
Is it RESTful to do something like /orders?status=fulfilled&customer.city=Atlanta?
Yes.
is there a canonical format for doing this sort of thing?
No.
You will normally want to choose a resource identifier that is compatible with a standardized URI Template because that lets you leverage pre-existing libraries.
But there are a lot of different ways you can expand variables into a template.
A query part composed of application/x-www-form-urlencoded key value pairs is a common choice; it gives you compatibility with HTML forms "for free". But if you aren't expecting clients to interact with your API via web pages, maybe that's not too important.
URI spellings are a lot like spellings of variable names; the machines don't care. You, therefore, have extra degrees of freedom that you can use to make life easier for some people: your clients looking at identifiers in their browsing history, your operations people looking in logs, your technical writers trying to document the API....
You'll probably want to choose something that is convenient for yourself -- so make sure that your design fits well with your routing framework.
Choosing identifier spellings that direct these requests to the same controllers that you are already using vs. a new controller -- that's entirely up to you. Part of the point of the API is that the implementation details are hidden from the client and can be changed without breaking the interface.
I am designing a REST API that will be used by several clients to query a data repository. I am anticipating that these clients will have different needs regarding the amount/level of detail of the responses.
Let's say I can query a collection of books. A book might potentially have lots of attributes (more than any single client might be interested in), maybe even subresources, and a client might request a large number of books, leading to a response body that is larger than required.
Therefore I am looking into ways of optimizing response size. The idea is to give the API client some means of specifying how much detail should be included in the response.
I would be interested to learn how this problem has been solved before; which mechanism worked well in practice and which didn't, which API design is particularly RESTful and which isn't, and so on.
A few ways I can think of how a client could possibly specify desired level of detail for the response:
Using either the GET or HEAD HTTP method / verb. The former would return all details, the former only a subset.
This approach only allows us to distinguish between two levels of detail, so it is of limited use.
Having a query string parameter that specifies (by name) which properties/attributes should be returned in the response. For example:
GET /books?include=title,author,publisher,...,preview
This offers almost unlimited flexibility, but this very flexibility might be difficult to actually implement and deal with (on both the client and server side).
Using different media types (one distinct media type per level of detail), selected via the Accept: header.
I don't really want to go down that route. I am not sure media types are appropriate for this purpose, and the world probably doesn't need more custom media types anyhow.
Using the profile relation / media type parameter. This seems a little better (no additional media types are required), but I am still unsure whether media types are the right method for selecting the "what" (content) of a response. They seem more appropriate solely for specifying the "how" (format) of the response.
For book collections (/books?publishedIn=1980s), only a small subset of all available data is returned, most importantly a href for each book that can be queried to get the full data about a single book.
This approach has at least two problems:
What attributes are included in collection responses besides the href links? Ideally, there is just enough additional data to satisfy most clients; otherwise...
Clients will have to perform lots of additional queries (one per book) to collect all the data that they need.
There are possibly more strategies for selecting the desired level of detail. I am interested to learn what works well in practice, without compromising RESTfulness too badly.
I think it depends mostly on how much flexibility you want to give to your API clients.
If you know the different uses of your data, you might want to define some available formats that your API can return.
For example, using this structure:
GET /books (with a default format if nothing is specified)
GET /books/minimal
GET /books/full
GET /books/otherformat
Note that this could also be using this URL structure if you don't want to duplicate your endpoints:
GET /books?format=minimal
However, in either case, this forces you to know exactly what data your clients will need or want at any given time.
I would not rely on media types as this might be more confusing for users than other more standard way of working with REST APIs.
[EDIT]
Also, should you decide to specify the whole list of fiends to return and find out that GET requests are not sufficient, you could refer to this post for an alternate way using POST requests
I'm completely new to REST. I helped to implement something that was called REST at work but it breaks so many of the rules that it's hard to qualify it as REST. I want to follow the HATEOAS guideline and the remaining question I have is regarding documentation of media types and their specification. Namely when one media type is really an extension of another.
For example, I've decided on 'application/hal+json' for the base media type. Everything that a user would receive is going to be a HAL blob with some added fields. I don't want to call my media types just 'application/hal+json', it seems to me more information should be available than that, but I want it to be clear that this is what they are in addition to the extra fields that are my data. Furthermore my system is going to end up having some of these fields inherited and such in both the request (which won't be HAL blobs) and response formats. A generic "User" type might have just a user id and name for example while an extension like "Student" or "Teacher" will have different additional fields.
Does it make sense to represent this extension somewhere in the media type itself? Do people generally document the relationship in their HATEOAS documentation links? If so, what's the general trend here? I want my API to be easy to use and thus figure it should follow norms that are available.
Couple of things i'd like to point out about your move to a true RESTful architecture.
First, RESTful APIs must perform content negotiation. To say your base type is hal+json is seems strange. It sounds like you want to have types like parent+hal+json or maybe hal+json;type=parent. This would mean your client would have to understand these types specifically...and this would be not very RESTful because it's just a local implementation. This is fine in the real world..you can do this...almost everyone does stuff like this.
To be true RESTful api you'd have to offer similar support for other content types...that could get messy.
Now specifically to HAL, there's two things available to you so that your client can "discover" what data types they are getting back. One is CURIEs and the other is Profiles https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-06#section-5.6 I think Profiles is more what you're after here as it allows you to document conventions and constraints for the resource that will be retrieved.
But don't count out CURIE's either. There's lots of defined semantics out there already. Your model might fit one of http://schema.org sets and then you can just use their link relationships and the client should know what's going on.
If you really want a lot of control on the semantics of your resources...you may want to look at http://json-ld.org/ with it's #context concept would be a good reference.
In my opinion this is an area where the examples are very thin, especially for HAL. I've yet to seen a client smart enough to parse and care about semantics at run time. What i think is important is when someone is building the client that info is available they can figure out that a Student is a Person. One day the thing building the clients will be client generator code and it'll use that info to build a nice client side object model for you.
TL;DR if you stick with HAL use CURIEs and Profiles to get what you want.
This question is an extremely open ended discussion and it really depends on how different engineers interpret REST standards and best practices. Nonetheless, As a fellow software engineer with enough experience with REST services development (and faced the same questions professionally as you did), I would add my inputs here.
REST service development rules are heavily dependent on the url definitions. It's very important that you expose your apis in such a way that your clients can understand exactly what's happening per api just by looking at the url definition.
With that being said, different clients (and for that matter different engineers) view the best practices differently. For example, if you are trying to search a User by email, there are atleast two approaches
1) GET /users/emails/{email} // A client can interpret this as
"getting a user by email"
2) GET /users?email={email} // A client can interpret this as
"searching a user by email" because of query param
3) GET /users/email={email} // This can be interpreted just as # 1
It depends on the developer how they want to expose this api and how they document it for the clients. All the approaches are correct in different perspectives.
Now going specific to your questions. Here's what my approach would look like in terms of "User", "Student" and "Teacher".
I look at each of these 3 as separate resources? Why? because they are separate types even though 2 of them are extended from the 3rd one. Now how would my apis look like for these?
For Student:
1) Retrieving a list of students : GET /students
2) Retrieving a Student with id: GET /students/{id}
3) Creating a Student : POST /students
4) Updating a student : PUT /students/{id}
5) Delete a student: DELETE /students/{id}
6) Search a student: GET
/students?{whateverQueryParamsYouWantForSearch}
The same will be applied for Teacher as well.
Now here's for User.
1) GET /users : Retrieving list of all the users (Students and
Teachers)
2) GET /users?type={type} : Here's the kicker. You can specify the
type to be student OR teacher and you will return the data of specific
type (properly documented ofcourse)
3) POST /users?type={type} : Create a specific TYPE of user
(student or teacher)
.. And so on.
The main difference is .. the apis with root url /users can be used for BOTH types of users (Provided the type is always specified and documented to the clients). While the Student and Teacher apis are specific to those types.
My money has always been on specific types while generic types for searching (meaning for searching both types of users .. use /users?params). It's the most easy way for the clients to understand what's going on. Even documenting them is much easier.
Finally talking about HATEOAS. Yes, it's a part of the standards and the best practice is to ALWAYS provide a url/link to the resource you are returning or if your return object is complex and contains other resources which might contain resources who might themselves be exposed through apis. For example,
/users?type=student&email=abc#abc.com
will return all users with that email and it's better to follow HATEOAS here and provide a url to each returned user such that the url looks like : /students/{id}. This is how we have normally handled HATEOAS
That is all I have to add. As I said earlier, its a very open ended discussion. Each engineer interprets the standards differently and there is no ONE WAY to handle all usecases. There are some base rules and the clients and other developers will applaud you if you follow them :)
I just began looking at REST and was wondering what the basic difference between the two representations was. The first one looks pretty nice to me and the second one has to pass some attribute values but the underlying logic seems to be boiling to almost the same thing (I could be mistaken though)
http://url/category/category_id/item_id
AND
http://url/category?category_id={12}&item_id={12334}
I think you are labouring under some fundamental misconceptions about what REST is about.
The URL used to access a resource really is a detail and actually should not matter to the client. URL's should really be "discovered" by clients anyway if they follow the HATEAOS principe that is one of the tenets of REST.
Essentially you are right though: either URL could represent the resource you are exposing in the end, but as I say, this really is a detail and it comes down to preference in many cases at what URL you expose something. The point of HATEOAS is to allow you to change the URL's that are used to access resources at-will without affecting clients that work against your existing services.
The following URL's might help you understand some of the properties that make services truly RESTful:
How to GET a cup of coffee
Describing RESTful Applications
[disclaimer: just because HATEAOS is a principle of REST does not make it easy to do. You will find most of the services on the web do not follow this principle strictly at all, as evidenced by their documentation which is full of URL templates; not the way services should be documented in the ideal world. I'm struggling myself to find good examples of truly RESTful services and clients...]
It should be possible for agents to reason about the resource structure:
based on the URL, and
based on links returned by requests for resources.
The problem with the second representation is that it can be considered as a set unordered keys and values, with no real structure/heirarchy.
If you click the button from your tag restful-url you get a good link from this site explaining the difference between those two styles:
How to obtain REST resource with different finder "methods"?
What is the benefit of referencing resources using globally-unique URIs (as REST does) versus using a proprietary id format?
For example:
http://host.com/student/5
http://host.com/student?id=5
In the first approach the entire URL is the ID. In the second approach only the 5 is the ID. What is the practical benefit of the first approach over the second?
Why does REST (seem to) go out of its way to advocate the first approach?
-- EDIT:
My question was confusing because it really asked two separate questions:
What is the benefit of addressibility?
What is the difference between the two URI forms seen above.
I've answered both questions below using my own post.
The main thing when i see uri's like that is a normal user would be able to remember that uri.
Us geeks are fine with question marks and get variables, but if someone remembers http://www.host.com/users/john instead of http://www.host.com/?view=users&name=john, then that is a huge benefit.
I will answer my own question:
1) Why are URIs important?
I'll quote from RESTful Web Services by Leonard Richardson and Sam Ruby (ISBN: 978-0-596-52926-0):
Consider a real URI that names a resource in the genre “directory of resources about
jellyfish”: http://www.google.com/search?q=jellyfish. That jellyfish search is just as
much a real URI as http://www.google.com. If HTTP wasn’t addressable, or if the Google
search engine wasn’t an addressable web application, I wouldn’t be able to publish that
URI in a book. I’d have to tell you: “Open a web connection to google.com, type ‘jellyfish’
in the search box, and click the ‘Google Search’ button.
This isn’t an academic worry. Until the mid-1990s, when ftp:// URIs
became popular for describing files on FTP sites, people had to write
things like: “Start an anonymous FTP session on ftp.example.com. Then
change to directory pub/files/ and download file file.txt.” URIs made
FTP as addressable as HTTP. Now people just write: “Download ftp://
ftp.example.com/pub/files/file.txt.” The steps are the same, but now they
can be carried out by machine.
[...]
Addressability is one of the best things about web applications. It makes it easy for
clients to use web sites in ways the original designers never imagined.
2) What is the benefit of addressibility?
It is far easier to follow server-provided URIs than construct them yourself. This is especially true as resource relationships become too complex to be expressed in simple rules. It's easier to code the logic once in the server than re-implement it in numerous clients.
The relationship between resources may change even though the individual resource URIs remain unchanged. For example, if Google Maps were to change the scale of their map tiles, clients that calculate relative tile positions would break.
3) What is the benefit of URIs over custom IDs?
Custom IDs identify a resource uniquely. URIs go a step further by telling you where to find it. This simplifies the client logic.
Search engine optimization mostly.
It also makes them easier to remember, and cleaner, more professional looking in my opinion.
The first is more aesthetically pleasing.
Technically there is no difference, but use the former when you can.
As Ólafur mentioned, The clarity of the former url is one benefit.
Another is implementation flexibility.
Let's say that student 5 changes infrequently. If you use the REST-style url you have the option of serving a static file instead of running code. In Rails it is common that the first request to students/5 would create a cached html file under your web root. That file is used to serve subsequent requests w/o touching the backend. Naturally, there's nothing rails specific about that approach.
The later url wouldn't allow for this. You can't have url variables (?, =) in the names of static pages.
Both URIs are valid from a REST perspective, however just realize that web caches treat the querystring parameters very differently.
If you want to use caching to your advantage then I suggest that you do not use a query string parameter to identify your resource.
I think it comes down to how closely you want to adhere to the principles of feng shui.