My thinking behind #3-type-things is that you might want to be able to do
both of these:
GET .../order -> all orders
GET .../order?t=org.openmrs.DrugOrder -> all drug orders

-Darius

On Thu, Apr 19, 2012 at 8:08 AM, Saptarshi Purkayastha <[email protected]>wrote:

> The Approach#3 is extremely complex and means that someone needs to
> understand the type of "what"
>
> A client does not have to understand the types, just resources and so to
> me the approach #1 is generalizable and concise to understand as a general
> pattern when having to communicate with OpenMRS web services. Again why
> would it be a problem to use Approach#1 with drugorder or laborder
> resource??
>
> ---
> Regards,
> Saptarshi PURKAYASTHA
>
> My Tech Blog:  http://sunnytalkstech.blogspot.com
> You Live by CHOICE, Not by CHANCE
>
>
>
> On 19 April 2012 06:43, Darius Jazayeri <[email protected]> wrote:
>
>> Hi All,
>>
>> We had a very good design call discussion on this, and Burke and I got
>> some brief, dense, and helpful insight on this from Jim Webber.
>>
>> The key insight: "Dealing with inheritance is easy: REST doesn't do it."
>> Basically: think of REST resources as simply exchanging documents. There
>> can be links between documents, but they are not allowed to have any formal
>> type hierarchy.
>>
>> So, after wrapping our heads around that, we've come up with three
>> different approaches to hide inheritance in the REST API, each applicable
>> to different things in the underlying Java class model:
>>
>> *Approach #1 - Subclass links to Superclass*
>> *Used for: Person/Patient*
>> In the REST API, the subclass document contains only subclass-specific
>> attributes, as well as a link to the superclass document. Example:
>> GET patient/1234 ->
>> {
>>     identifiers: [ ... ],
>>     person: { ref representation of person/1234 }
>> }
>>
>> Even though the underlying Patient object inherits from Person, the
>> PatientResource should hide this. Thus you cannot edit a birthdate via the
>> patient resource, *and* creating a patient requires two POSTs (one to
>> create a person resource, the next to create a patient resource that links
>> to the person resource).
>>
>> *Approach #2 - Hide the Superclass*
>> *Used for: ActiveListItem/Allergy/Problem*
>> We use this approach when the multiple subclasses are not meaningfully
>> related to each other, and they only share a superclass for ease of
>> implementation. The REST API has no resource for the superclass. Each
>> subclass is its own resource, which contains the union of the properties of
>> its superclass and itself.
>>
>> *Approach #3 - Single Resource for Class Hierarchy*
>> *Used for: Concept/ConceptNumeric/ConceptComplex*
>> *Used for: Order/DrugOrder/XyzModuleOrder*
>> We use this approach when multiple subclasses really are different
>> versions of the same basic thing. In other words, they inherit the meaning
>> of the superclass, not just its implementation details.
>> The REST API has a single resource (Concept, Order) that manages the
>> documents for all subclasses. Each document represents an underlying
>> instance of some class in the hierarchy, and it contains all properties of
>> that class, including inherited ones.
>> For example, GET order?patient=1234 ->
>> [
>>     {
>>         type: "org.openmrs.DrugOrder",
>>         startDate: "2011-01-01",
>>         // other Order properties go here
>>         dosage: "100mg",
>>         // other DrugOrder properties go here
>>         links: [ { rel: "self", uri: "order/11111" } ]
>>     },
>>     {
>>         type: "org.openmrs.Order",
>>         startDate: "2011-02-03",
>>         // other Order properties go here
>>         links: [ { rel: "self", uri: "order/22222" } ]
>>     },
>>     {
>>         type: "org.openmrs.module.lab.LabModuleOrder",
>>         startDate: "2011-03-04",
>>         // other Order properties go here
>>         specimen: { ref representation of a lab specimen },
>>         // other LabModuleOrder properties go here
>>         links: [ { rel: "self", uri: "order/33333" } ]
>>     }
>> ]
>>
>> I've put a discriminator field in here ("type" might not be a safe name)
>> because it seems quite useful, and I think it's necessary for object
>> creation.
>> For example: POST order
>> {
>>         type: "org.openmrs.module.lab.LabModuleOrder",
>>         startDate: "2011-03-04"
>> }
>> ...will be delegated to the registered handler for LabModuleOrder, rather
>> than being handled directly by OrderResource.
>>
>> Implementation-wise:
>>
>>    - we are going to count on the underlying OpenMRS API (and ultimately
>>    Hibernate) to work such that if we do 
>> OrderService.getOrdersByPatient(1234)
>>    we get back a List<Order> whose individual items are actually of their
>>    correct subclasses.
>>    - the core RESTWS module, and other modules, need to register
>>    handlers for their known subclasses
>>    - we will have to write some code, but that's the fun part. :-)
>>
>> Thoughts?
>>
>> -Darius
>>
>>
>> On Wed, Apr 18, 2012 at 6:35 AM, Burke Mamlin <[email protected]>wrote:
>>
>>> My biggest concern is that it requires that consumers of the API
>>> know/learn our data model; however, since the person is presented as a
>>> property of the patient and gender as a property of the person (not the
>>> patient directly), it's about as good a solution as I can imagine.
>>>
>>> -Burke
>>>
>>>
>>> On Tue, Apr 17, 2012 at 10:42 PM, Darius Jazayeri 
>>> <[email protected]>wrote:
>>>
>>>> Yes, I meant what you said Burke.
>>>>
>>>> (Hopefully that was my only typo.)
>>>>
>>>> -Darius (by phone)
>>>> On Apr 17, 2012 6:48 PM, "Burke Mamlin" <[email protected]>
>>>> wrote:
>>>>
>>>>> Darius,
>>>>>
>>>>> Did you mean to two posts, one to patient & the other to person?  Both
>>>>> of yours were to the same resource.
>>>>>
>>>>> This implies that if you want to modify a patient's gender *and* 
>>>>> identifiers,
>>>>>> you have to do *two* POSTs.
>>>>>> For example:
>>>>>> POST patient/abcd1234 { identifiers: [ ... ] }
>>>>>> POST *person*/abcd1234 { gender: 'M' }
>>>>>
>>>>>
>>>>> Cheers,
>>>>>
>>>>> -Burke
>>>>>
>>>>> On Tue, Apr 17, 2012 at 8:01 PM, Darius Jazayeri 
>>>>> <[email protected]>wrote:
>>>>>
>>>>>> Hi All,
>>>>>>
>>>>>> On tomorrow's design call one topic we will discuss is how to
>>>>>> properly represent inheritance and subclasses in a RESTful way. Fun and
>>>>>> exciting background discussion can be found on the ticket:
>>>>>> https://tickets.openmrs.org/browse/RESTWS-221. Call-in details are
>>>>>> here <https://tickets.openmrs.org/browse/RESTWS-221>.
>>>>>>
>>>>>> My proposal, generally supported by Saptarshi, and disliked by Roger,
>>>>>> is that we represent a subclass as basically the composition of a
>>>>>> superclass resource, and a subclass resource contains subclass-specific
>>>>>> properties, and a pointer to the superclass.
>>>>>>
>>>>>> For example: GET patient/abcd1234 ->
>>>>>> {
>>>>>>     identifiers: [ ... ], // this is the only Patient-specific
>>>>>> property
>>>>>>     links: [
>>>>>>         { rel: "self", uri: "patient/abcd1234" }
>>>>>>     ],
>>>>>>     person: { // this is a pointer to the superclass
>>>>>>         names: [ ... ],
>>>>>>         gender: 'M',
>>>>>>         // other properties on the Person superclass follow
>>>>>>         links: [
>>>>>>             { rel: "self", uri: "person/abcd1234" }
>>>>>>         ]
>>>>>>     }
>>>>>> }
>>>>>>
>>>>>> This implies that if you want to modify a patient's gender *and* 
>>>>>> identifiers,
>>>>>> you have to do *two* POSTs.
>>>>>> For example:
>>>>>> POST patient/abcd1234 { identifiers: [ ... ] }
>>>>>> POST patient/abcd1234 { gender: 'M' }
>>>>>>
>>>>>> You should be able to *create* a patient in a single POST, but not
>>>>>> update one that way.
>>>>>>
>>>>>> At first this seems inconvenient, and unintuitive for someone who's
>>>>>> used to the OpenMRS Java API. The reason for this is that I think it's
>>>>>> necessary to support web-standard caching, which allows web service
>>>>>> scalability. Basically, imagine that someone may be running a 
>>>>>> reverse-proxy
>>>>>> on their server, which caches resources generated by the server and 
>>>>>> serves
>>>>>> them up to many web clients, relieving server load. In order for that
>>>>>> reverse-proxy cache to avoid serving up stale data, we cannot allow doing
>>>>>> POST patient/abc123 to modify the resource at person/abc123. (According 
>>>>>> to
>>>>>> web standards, if the cache sees a POST to patient/abc123, this 
>>>>>> invalidates
>>>>>> that specific cache entry, but all of this is invisible to the
>>>>>> server.) Thus my proposal.
>>>>>>
>>>>>> I'm only moderately certain I'm approaching this right, so if you
>>>>>> know or suspect the right answer to this problem (especially if it's
>>>>>> different from my proposal), please reply and/or join us on the design 
>>>>>> call
>>>>>> tomorrow!
>>>>>>
>>>>>> -Darius
>>>>>>
>>>>>> PS- The other topic we'll discuss on the call is Wyclif's proposal
>>>>>> for a module, that will allow us to reboot our implementation of orders 
>>>>>> and
>>>>>> order entry, such that we implement something better, and it runs on both
>>>>>> old and new versions of OpenMRS. All in all this will be an action-packed
>>>>>> call.
>>>>>> ------------------------------
>>>>>> Click here to 
>>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from
>>>>>>  OpenMRS Developers' mailing list
>>>>>
>>>>>
>>>>> ------------------------------
>>>>> Click here to 
>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from
>>>>>  OpenMRS Developers' mailing list
>>>>
>>>> ------------------------------
>>>> Click here to 
>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from
>>>>  OpenMRS Developers' mailing list
>>>>
>>>
>>> ------------------------------
>>> Click here to 
>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from 
>>> OpenMRS Developers' mailing list
>>>
>>
>>
> ------------------------------
> Click here to 
> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from 
> OpenMRS Developers' mailing list
>

_________________________________________

To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to 
[email protected] with "SIGNOFF openmrs-devel-l" in the  body (not 
the subject) of your e-mail.

[mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]

Reply via email to