Stream: implementers
Topic: Transactions
Jason Walonoski (Feb 26 2016 at 14:59):
I wrote a post about transactions, as it was a topic of some confusion on the Skype channels a few days ago.... http://lightmyfhir.org/2016/02/26/fhir-transactions/
Josh Mandel (Feb 26 2016 at 16:13):
Thanks @Jason Walonoski!
Where did you get the idea that:
"subject":{"reference":"Patient/9e33a01d-c35f-4920-9179-50d5b8a6f992"},
is the way to refer to a patient from an Observation in a bundle?
Josh Mandel (Feb 26 2016 at 16:15):
On my reading, it should just be:
"subject":{"reference":"urn:uuid:9e33a01d-c35f-4920-9179-50d5b8a6f992"},
(But unless there's an example one way or the other, I'm sure it's just ambiguous.)
On this same topic, Dan Gottlieb and I worked out these scenarios -- but this involved guesswork too.
Jason Walonoski (Feb 26 2016 at 18:01):
@Josh Mandel to be honest, I wasn't sure if the urn:uuid should go in the reference or not.
Jason Walonoski (Feb 29 2016 at 13:36):
@Grahame Grieve wrote:
Jason - thanks for the blog post. I don't really like the idea of creating yet another transaction type - specially one that overlaps so much with transaction. But I do think you captured the use case - get a graph of records, push them elsewhere.
so let's say, you get a $everything, and you want to post it to the server, and you can't dictate the ids to the server. So we want the client to do as little as possible and still have the semantics clear, right? And you're concerned that they're not (and Josh really is too).
so really, let's say that the client has to minimally change the batch type to transaction, and populate the request - that has to be done. What we clearly don't want to do is have the client have to touch any of the ids - we want the server to have to do all that
so it seems that the sweetest solution to this is to allow all the ids to be populated in the resources, and avoid the in/out UUID confusion you ran into, and just say, make the request a POST to /base, and the server can infer, from the type and id, that you want it to sort out the ids however it does. And so post to [base] inside a transaction has a special meaning. And then we say, if a client explicitly makes it a PUT to a full id, then either the server honours it or not.
I think those are light changes to the spec, and the implementations, but remove the potential for confusion...?
Jason Walonoski (Feb 29 2016 at 13:38):
@Grahame Grieve So, when you say
make the request a POST to /base
Are you talking about the transaction POST to /base, or the Bundle.entry.request.method="POST"
and Bundle.entry.request.url="[base]"
?
Grahame Grieve (Feb 29 2016 at 13:39):
second
Jason Walonoski (Feb 29 2016 at 13:41):
And if they POST to base, then the client is assuming that the server will do things like patient matching and possible record de-duplication?
Grahame Grieve (Feb 29 2016 at 13:41):
hmm. I'm not sure how far that assumptions should go?
Jason Walonoski (Feb 29 2016 at 13:42):
Me either. That is why I was suggesting a new transfer
code or new $transfer
operation.
Grahame Grieve (Feb 29 2016 at 13:43):
I think that's orthogonal. You'd still have to state the assumptions either way
Jason Walonoski (Feb 29 2016 at 13:45):
I agree, but a new code or operation makes it very explicit (and hopefully obvious) to both parties. I'm not tied to that proposal though.
Grahame Grieve (Feb 29 2016 at 13:46):
well, you might argue that it's less obvious, but I don't think we want to create a whole new operation for it. But it's hard to progress if we can't resolve the assumptions
Jason Walonoski (Feb 29 2016 at 13:50):
OK. So... here it goes:
- If the client specifies
Bundle.entry.request.method="POST"
andBundle.entry.request.url="[base]"
during a transaction, the server assumes this record is a transfer from another system. There may already exist duplicate records on the server. The server determines the outcome of each operation. The server must maintain the graph of resources in the entire transaction, but not the specific IDs given. - If the client specifies other
Bundle.entry.request.method && Bundle.entry.request.url
combinations (with or without conditional modifiers), then the client is specifying that it knows exactly what it wants to do with the resource. The server replies normally for each operation.
Grahame Grieve (Feb 29 2016 at 13:55):
So it's server discretion to decide one what basis something is a duplicate?
Jason Walonoski (Feb 29 2016 at 13:56):
Well, I don't know, this is my suggestion. I think it makes sense that way though, because the client doesn't know what the server has (and may not have permission to search all the resources to do that either)... it just wants to transfer a patient record.
Grahame Grieve (Feb 29 2016 at 13:59):
I think it makes sense. But then I'm thinking about transferring a document rather than data. In that case, you don't want the server to have such freedom. But then I think you'd be posting to /binary, not asking the server to treat it as a transaction. The relevant spec is
Grahame Grieve (Feb 29 2016 at 14:00):
http://hl7.org/fhir/documents.html#bundle
Grahame Grieve (Feb 29 2016 at 14:00):
and yes: "Ignore the fact that the bundle is a document and process all of the resources that it contains as individual resources. Clients SHOULD not expect that a server that receives a document submitted using this method will be able to reassemble the document exactly"
Grahame Grieve (Feb 29 2016 at 14:00):
ok. so I think I agree
Jason Walonoski (Feb 29 2016 at 14:02):
So, that requires the client to create a Composition as the first entry... also the Bundle.type="document"
rather than transaction.
Grahame Grieve (Feb 29 2016 at 14:07):
well, that assumes that they already had a document (as opposed to say, an $everything)
Jason Walonoski (Feb 29 2016 at 14:16):
OK, so I think we agree on the assumptions (as stated in the bullets). And you want to avoid a new operation. I understand... So, what about a new Bundle.type="transfer"
code? Or do you want to continue to use transaction
or searchset
(the result of the $everything) with the given rules on posting to base?
Josh Mandel (Feb 29 2016 at 15:09):
I think l agree with this proposed behavior, but I don't understand how it's different from the current spec; can someone explain what would actually be changing?
Jason Walonoski (Feb 29 2016 at 16:10):
Josh, great question... I was trying to hash that out with Grahame above... I don't think we're there yet.
Josh Mandel (Feb 29 2016 at 16:11):
OK, fair enough. Basically saying "client-supplied are preserved for PUT
, but the server can assign at will on POST
" seems sane to me.
Jason Walonoski (Feb 29 2016 at 16:12):
Along with examples for linking resources... and probably some other stuff.
Josh Mandel (Feb 29 2016 at 16:13):
Definitely lots of examples are needed! I'm just trying to make sure we agree about what they should _say_.
Jason Walonoski (Feb 29 2016 at 16:22):
Well, we've been talking about having POST
to [resourceType]
assumes the client wants to make a create, and POST
to [base]
means this is a transfer -- so it might not be a create (it could be an update) -- and the client doesn't need to generate complicated IfNoneMatch
type of conditionals. Leaves it to the server to de-duplicate. Allows the client to say "I want to transfer this patient record, but I don't have the authority to tell you how to do patient matching or access your other records"
Ewout Kramer (Feb 29 2016 at 17:16):
"I want to transfer this patient record, but I don't have the authority to tell you how to do patient matching or access your other records"
My gut feeling says this will turn out to be another kind of bundle in the end, instead of doing this implicitly by changing where we POST to. The fact that using this kind of POST to base only makes sense in the context of a Bundle (i.e. posting a single resource to the REST endpoint is not meaningful and not even possible currently), suggests this is a kind of bundle, rather than a kind of REST operation.
Grahame Grieve (Feb 29 2016 at 17:18):
well, if we changed to a different kind of bundle, what would we do with request?
Grahame Grieve (Feb 29 2016 at 17:19):
an alternative is that we deem that this language applies:
Grahame Grieve (Feb 29 2016 at 17:19):
file:///C:/work/org.hl7.fhir/build/publish/http.html#other-bundles
Jason Walonoski (Feb 29 2016 at 18:06):
One issue with current wording of the #other-bundles link, is that the matching is done on "identity" -- does that mean id
or Resource.identifier
or the concept of identity?
Grahame Grieve (Feb 29 2016 at 19:07):
whoops I used my local link sorry.
Chris Grenz (Mar 01 2016 at 14:53):
If I'm following this correctly, this seems to be closely related to identity resolution as would be important in messaging (esp. @Ewout Kramer 's use case). We're using small contained resources here (basically only an identifier element), but am very interested in this discussion (getting folks to think about the messaging implications).
Jason Walonoski (Mar 07 2016 at 16:54):
Technically this is a Batch question, but it make sense to me to include it in the transactions topic...
The specification says this about Batch processing rules:
For a batch, there SHALL be no interdependencies between the different entries in the Bundle. The success or failure of one entry SHALL not alter the success or failure or resulting content of another. Servers SHALL validate that this is the case. Note that it is considered that servers execute the batch in the same order as that specified below for transactions, though the order of execution should not matter given the previous rule.
What is an "interdependency" between entries? An Observation.subject reference to a Patient in the Bundle? I'm trying to create an example to test that servers do "validate that this is the case."
Lloyd McKenzie (Mar 07 2016 at 17:15):
A situation where you're creating a patient and then referencing it with an observation that's defined in the same batch - if the creation of the patient fails or doesn't happen before the observation, then the batch will fail - and that would be a violation of the rule.
Jason Walonoski (Mar 07 2016 at 18:50):
But if the Patient creation succeeds, the wording suggests it is still a violation of the rule, because it is an interdependency. So, the whole batch should fail, or just the two entries?
Grahame Grieve (Mar 07 2016 at 19:16):
discretion of the server at the moment
Grahame Grieve (Mar 07 2016 at 19:17):
I would say, creating a patient, searching by the newly creatd patient is also a dependency
Grahame Grieve (Mar 07 2016 at 19:17):
there's some looseness to the definition for a reason
Jason Walonoski (Mar 07 2016 at 21:32):
That makes it hard to test.
Grahame Grieve (Mar 07 2016 at 21:33):
yes. indeed. we could certainly define something almost useless so it would be easy to test. The question is where the right balance is
Jason Walonoski (Mar 07 2016 at 21:34):
Well, shouldn't it be a "SHOULD" then, rather than a "SHALL"?
Grahame Grieve (Mar 07 2016 at 21:35):
maybe.
Jason Walonoski (Mar 07 2016 at 21:36):
OK. I'll submit a change request, and people can vote on it.
http://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=9681
Paul Knapp (Mar 08 2016 at 05:29):
I think the intention is that each entry is actioned in order and the sucess or failure of each is independant, although it is recognised that each is dependant on the overall state of the world at the point of action. So yes if the patient create fails the observation fails but due to the lack of the patient 'in the world' not because of the failure in the batch. For example the failure of a create for any other patient in the batch would not fail the rest of the entries in the batch. The outcome of the each of the entries in the batch is the same as had the entries been applied separately, not in a batch, in the same order as they appear in the batch.
Jason Walonoski (Mar 08 2016 at 12:48):
But Paul, there is nothing that says the Observation create has to fail. It makes sense that it fails, and some servers might enforce that Observation.subject references a valid and resolvable Patient, but the spec doesn't mandate that. This is why I submitted a change to SHOULD, because the SHALLs as written are untestable.
Lloyd McKenzie (Mar 08 2016 at 15:37):
Whether the Observation create fails or not, it's a dependency, which means it's a non-conformant batch. It's a static test, not a runtime test.
Jason Walonoski (Mar 08 2016 at 15:44):
So, are you saying that any static references across Bundle.entry.resource in a batch are non-conformant?
Lloyd McKenzie (Mar 08 2016 at 15:48):
Static references to things being created would be non-conformant
Josh Mandel (Mar 08 2016 at 17:20):
I think I need help (like a good + bad example) to understand this point.
Grahame Grieve (Mar 08 2016 at 19:01):
you can't make a static reference to a thing being created in a batch. THe id pattern we use in a transaction - that would be impossible in a batch.
Grahame Grieve (Mar 08 2016 at 19:01):
so that would be clearly a fail
Grahame Grieve (Mar 08 2016 at 19:02):
you can also do sneaky references between resources using server functionality - conditional create followed by conditional update of the same thing. We won't a 'don't do that' on there
Vadim Peretokin (Sep 25 2016 at 22:38):
Are there any public servers available that support transactions?
Grahame Grieve (Sep 25 2016 at 22:44):
mine does
Grahame Grieve (Sep 25 2016 at 22:44):
I think the HAPI one does too
Vadim Peretokin (Sep 25 2016 at 23:51):
Hmm... yours didn't return me a bundle-transaction
Vadim Peretokin (Sep 25 2016 at 23:51):
So I don't know the IDs of the resources that were created
Vadim Peretokin (Sep 25 2016 at 23:52):
HAPI said "Unable to store a Bundle resource on this server with a Bundle.type value of: transaction" :\
Grahame Grieve (Sep 26 2016 at 00:26):
what did it return?
Vadim Peretokin (Sep 26 2016 at 00:30):
Returned me the Bundle as-is, so just like any other resource.
Vadim Peretokin (Sep 26 2016 at 00:31):
So that made is difficult or impossible to figure out what happened with all my operations
Grahame Grieve (Sep 26 2016 at 00:32):
sounds like you're doing something wrong. what are you posting where/
Vadim Peretokin (Sep 26 2016 at 00:33):
Yeah probably. I'm posting the transaction example (http://hl7.org/fhir/2016Sep/bundle-transaction.json.html) to http://fhir3.healthintersections.com.au/open/Bundle
Vadim Peretokin (Sep 26 2016 at 00:33):
Take out the Parameters entry, that part errors
Grahame Grieve (Sep 26 2016 at 00:34):
if you post a bundle to /Bundle, it will be stored as is, irrespective of it's bundle type
Vadim Peretokin (Sep 26 2016 at 00:36):
Yep I see. Thanks
Brian Postlethwaite (Sep 27 2016 at 12:15):
Mine should work too
James Agnew (Sep 30 2016 at 21:43):
FYI- HAPI only lets you post a bundle with type "document" or "collection" to the [base]/Bundle
endpoint. Transactions have to be posted to [base]/
nicola (RIO/SS) (Oct 12 2016 at 09:42):
fhirbase & aidbox does
Ben Spencer (Apr 06 2017 at 10:35):
Hi, having trouble understanding a couple of the rules for resource IDs in transaction bundles:
from https://www.hl7.org/FHIR/bundle.html#references:
"If the fullUrl starts with urn:uuid: or urn:oid:, then append the id to the base URL and try to resolve within the bundle as for a RESTful URL reference"
What specifically do "id" and "base URL" refer to here? Is there an example of this kind of resolution?
from http://hl7.org/fhir/http.html#transaction:
"For updates, the server performs a mapping between the fullUrl specified and the local URL the server knows that instance as, if possible. If the server does not have a mapping for the fullUrl, the server ignores the base URL and attempts an update assuming the base is the same as the server base"
Does this mean that the ID in request.url for a PUT request is irrelevant and only the fullUrl matters? Or should the server enforce that they (and the ID in the resource) match? And does the same rule apply to DELETE?
Lloyd McKenzie (Apr 06 2017 at 14:52):
The server should check alignment between the entry.fullUrl and the entry.resource.id. Failure to align probably means bad things, but as usual, servers aren't obligated to validate inbound instances. fullUrl should not be present for transactions and batches (which would be the situation where you'd have a request.url)
Lloyd McKenzie (Apr 06 2017 at 14:54):
Actually, I misread on the last sentence. I'm actually not sure what the purpose is of having both a fullUrl and a requestUrl, so I'll let someone else respond.
Angus Millar (Apr 10 2017 at 02:00):
Given a Bundle Batch / Transaction, how does the client who receives the transaction response from the server identify which resource is which. If I was to send in two resources, both Patient resources as POSTs. One for Patient Bob and one for Patient Jane, were each resource has no Resource ID as the server will assign them, yet each does have a UUID in the FullURL of each entry.
The Transaction response may return that both were committed ‘Created 201’ in the entry.response.status and now I want to obtain from the response the server assigned Resource Ids for each. How do I know which is Bob and which is Jane without inspecting the patient names of course.
I had thought that the entry.FullURL would be returned unchanged and that was my key for reading the Transaction response, yet the examples in the spec do not indicate this, the examples have updated the entry.FullURL to the new location in the server, which feels wrong because the response entry.response.location already conveys this information. Are the examples wrong? Should the entry.FullURL remain unchanged between submission and response of the transaction bundle?
The only other way I see this working is if the transaction response entries are guaranteed to be returned in the same order they were sent. Yet that feel a little bit like crossing my fingers and hoping?
Brian Postlethwaite (Apr 10 2017 at 03:35):
That feels like something that deserves a tracker be created Angus.
Angus Millar (Apr 10 2017 at 04:14):
Ok I added it to the tracker.
Ben Spencer (Apr 10 2017 at 09:03):
they are guaranteed to be returned in the same order
that doesn't seem like an ideal way to match them up though
Angus Millar (Apr 10 2017 at 23:44):
Yes I think this the intent of the spec. I did more work on this in the past 24hrs and have realized that you cannot use the FullUrl as I was thinking, as a key to each resource in the bundle. If you have GET requests in the transaction bundle then there is not FullUrl and if that GET is a search then the return Transaction response also has no FullUrl as it is a search result bundle in the Transation bundle which also has not FullUrl. I’m also not sure you can return a FullUrl for a DELETE request.
I have now accepted that it is true that the server, or at least mine, will always return a transaction response bundle that contains entries which are one-to-one with the transaction bundle received. Or else, if an issue occurs whereby the whole transaction cannot be committed then a single OperationOutcome resource is returned stating the issue encountered and referencing the entry by index that the issue was found in (should that be a zero based index or one based. Who knows, Zero based for me).
Perhaps the Transactions page in the spec could have talked to this point. I did find this comment inside the bundle-response XML example in the spec: “one entry for each entry in the transaction, in order, with a response”. Which is what cemented it for me, yet as a comment in an example, seems an odd place to state such a point.
Ben Spencer (Apr 11 2017 at 09:23):
That (well, similar) text is in the spec too: http://hl7.org/fhir/http.html#transaction-response
Angus Millar (Apr 12 2017 at 06:38):
Yes correct, it is in the spec. I missed it. Thanks for pointing it out.
Dexter (Dec 01 2020 at 12:51):
I'm not sure what I'm getting wrong?
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"resource": {
"id": "20441865",
"resourceType": "Patient",
"name": [
{
"use": "official",
"given": [
"80"
],
"family": "80"
}
]
},
"request": {
"method": "POST"
}
},
{
"resource": {
"resourceType": "CareTeam",
"subject": {
"reference": "Patient?_id=20441865",
"type": "Patient"
},
"status": "active"
},
"request": {
"method": "POST"
}
}
]
}
Except for transactions and batches, each entry in a Bundle must have a fullUrl which is the identity of the resource in the entry. Note that this is not a versioned reference to the resource, but its identity. Where a resource is not assigned a persistent identity that can be used in the Bundle, a UUID should be used (urn:uuid:...).
For transactions and batches, entries MAY not have fullURLs when the entry.request.method = POST, and the resource has no identity. Note that even in this case, there may still be a fullURL in a transaction on a POST so that relationships between resources can be represented (see Transactions).
From the docs I understand this as, "It's enough to make sure the fake IDs you provide match, and they'll be appropriately referenced". But I get this error, what am I missing?
Invalid match URL \"Patient?_id=20441865\" - No resources match this search"
Dexter (Dec 01 2020 at 13:01):
Hmm I see I think I must use the mentioned ID types, such as UUID, UID etc
Dexter (Dec 01 2020 at 13:32):
Hmm still doesn't seem to work when using UUID
Dexter (Dec 01 2020 at 13:44):
This doesn't work,
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"resource": {
"fullUrl": "urn:uuid:6a2f70be-be02-4dd4-94a3-44f326b9f93f",
"resourceType": "Patient",
"name": [
{
"use": "official",
"given": [
"80"
],
"family": "80"
}
]
},
"request": {
"method": "POST"
}
},
{
"resource": {
"resourceType": "CareTeam",
"subject": {
"reference": "Patient?_id=6a2f70be-be02-4dd4-94a3-44f326b9f93f",
"type": "Patient"
},
"status": "active"
},
"request": {
"method": "POST"
}
}
]
}
but this does! What is the difference? As far as I can tell, the UUID seem okay to my untrained eye
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"resource": {
"fullUrl": "urn:uuid:61ebe359-bfdc-4613-8bf2-c5e300945f0a",
"resourceType": "Patient",
"name": [
{
"use": "official",
"given": [
"80"
],
"family": "80"
}
]
},
"request": {
"method": "POST"
}
},
{
"resource": {
"resourceType": "CareTeam",
"subject": {
"reference": "Patient?_id=61ebe359-bfdc-4613-8bf2-c5e300945f0a",
"type": "Patient"
},
"status": "active"
},
"request": {
"method": "POST"
}
}
]
}
Only difference is the ID!
6a2f70be-be02-4dd4-94a3-44f326b9f93f
-> Doesn't work
61ebe359-bfdc-4613-8bf2-c5e300945f0a
-> Works
Vassil Peytchev (Dec 01 2020 at 13:46):
Since your transaction is attempting the PATCH an existing resource, you must know and provide the actual resolvable fullUrl of that resource as it exists on the server where the PATCH is supposed to occur. You can't use a UUID in this case.
Dexter (Dec 01 2020 at 13:46):
Patch? I don't have any PATCH in the last 2 questions I sent
Vassil Peytchev (Dec 01 2020 at 13:48):
I got confused with the topic of the discussion. Do you mind editing the title on your first post?
Dexter (Dec 01 2020 at 13:49):
Ahh my apologies, I replied to a post that solved my previous question, and posted the next in the same place. Hope that's okay!
Vassil Peytchev (Dec 01 2020 at 13:57):
Back to your first example - have you tried using
"subject": {
"reference": "Patient/20441865",
"type": "Patient"
}
the reference in subject is supposed to be in a /[type]/[id]
format. I am pretty sure Patient?_id=20441865
is incorrect. And I have no clue why the example with UUID works at all...
Michele Mottini (Dec 01 2020 at 14:31):
fullUrl
is not a resource property, it should be one level up
Michele Mottini (Dec 01 2020 at 14:32):
The server you are using might be accepting it for whatever reason, but it is definitely wrong
Dexter (Dec 01 2020 at 15:19):
Yes! Misplaced the fullUrl
field. Fixed it now, still doesn't work.
I replicated the UUID example from the examples here.
Dexter (Dec 01 2020 at 15:21):
Now it does! Had to change the reference to Patient/urn:uuid:6a2f70be-be02-4dd4-94a3-44f326b9f93f
!
Paul Church (Dec 01 2020 at 15:30):
The reference shouldn't have "Patient/", it should just be the urn.
Paul Church (Dec 01 2020 at 15:31):
There's an example here: https://cloud.google.com/healthcare/docs/how-tos/fhir-bundles#resolving_references_to_resources_created_in_a_bundle
This is the google documentation but hopefully our interpretation is the same as others!
Paul Church (Dec 01 2020 at 15:33):
Using "reference = Patient?_id=xxx" is a conditional reference which is a different thing than bundle fullUrl resolution. It searches for resources that already exist on the server. There was a thread a while ago about whether this search also finds things inside the bundle, I think implementations vary.
Dexter (Dec 01 2020 at 15:35):
Paul Church said:
The reference shouldn't have "Patient/", it should just be the urn.
I see, I couldn't find an example on the FHIR documentation, so I assumed I could use Patient/urn:uuid:ID
. But now I know, thanks!
Marcin Szewczyk (Dec 08 2020 at 14:49):
Question regarding update in bundle transaction and fullUrl mappings.
"For updates, the server performs a mapping between the fullUrl specified and the local URL the server knows that instance as, if possible."
How mapping should be stored on fhir server? as seperate entity? or any metadata?
Michele Mottini (Dec 08 2020 at 15:05):
The mapping is not stored, it is used just during the processing of the transaction
Marcin Szewczyk (Dec 08 2020 at 15:37):
do not understand, so in which cases server do not know mapping?
"For updates, the server performs a mapping between the fullUrl specified and the local URL the server knows that instance as, if possible."
or example:
- POST create Patient fullURL=UUID1, identifier=xyz.com/Patient/123 send to abc.com FHIR SERVER -> returns abc.com/Patient/987
- PUT Patient fullUrl=xyz.com/Patient/123 send to abc.com FHIR server -> is this valid scenario?
or
it should be
PUT Patient fullUrl=abc.com/Patient/987 send do abc.com FHIR server
Marcin Szewczyk (Dec 11 2020 at 06:15):
Marcin Szewczyk said:
do not understand, so in which cases server do not know mapping?
"For updates, the server performs a mapping between the fullUrl specified and the local URL the server knows that instance as, if possible."or example:
- POST create Patient fullURL=UUID1, identifier=xyz.com/Patient/123 send to abc.com FHIR SERVER -> returns abc.com/Patient/987
- PUT Patient fullUrl=xyz.com/Patient/123 send to abc.com FHIR server -> is this valid scenario?
or
it should be
PUT Patient fullUrl=abc.com/Patient/987 send do abc.com FHIR server
Any ideas about this?
Reading further: image.png
There is two suggestions:
-
Fhir Server should have ability to understand identifier with base from other server.
just for the sake of simplicity for client/complexity for server...
" This allows the same transaction bundle to be sent to multiple systems without changing the fullUrls for each target."
in other words: server abc.com should understand PUT Bundle transaction with xyz.zom/Patient/123
am i wrong? -
on the other hand, fhir server MAY accept foreign fullUrl as their own... under some circumstances
"When processing a batch or transaction, a server MAY choose to honor existing logical ids (e.g. Observation/1234 remains as Observation/1234 on the server), but since this is only safe in controlled circumstances, servers may choose to assign new ids to all submitted resources, irrespective of any claimed logical id in the resource, or fullUrl on entries in the batch/transaction."
Lloyd McKenzie (Dec 11 2020 at 14:04):
The most common approach is to assign whatever identifiers you like and then to go back and update all links to point to the identifiers you've assigned
Marcin Szewczyk (Dec 14 2020 at 07:29):
Lloyd McKenzie said:
The most common approach is to assign whatever identifiers you like and then to go back and update all links to point to the identifiers you've assigned
That is my way of doing integrations from notFHIR world
But FHIR standard suggests to respect others ids, to enable sending same Bundle to multiple without changing Bundle content - looks like utopia..
I am thinking of doing conditional PUT with identifier parameter - thats way both internal and external id will be supported.
As long as we store both of them on identifier list
Dexter (Jan 22 2021 at 11:42):
References within a Bundle.entry.resource to another Bundle.entry.resource that is being created within the batch are considered to be non-conformant.
Does this mean that I can't create, say, a Patient
resource and a CareTeam
at once in which the CareTeam
refers to the Patient
?
Dexter (Jan 22 2021 at 12:05):
I'm creating this POST
transaction
where I'm trying to do 3 things. Create a Patient
, create a CareTeam
for that Patient
, and then assign a device to that Patient
. Here's what I have (POST bundle below). I can't seem to get the device assignment working, the reference on the device retains the urn
, instead of resolving to the patient ID, like in the created CareTeam
of the request. What am I missing?
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"fullUrl": "urn:uuid:abe0b81e-2aca-44c7-8469-1dc1f7301fe9",
"resource": {
"resourceType": "Patient",
// patient info removed for brevity
},
"request": {
"method": "POST"
}
},
{
"resource": {
"resourceType": "CareTeam",
"subject": {
"reference": "urn:uuid:abe0b81e-2aca-44c7-8469-1dc1f7301fe9",
"type": "Patient"
},
// removed for brevity
"status": "active"
},
"request": {
"method": "POST"
}
},
{
"resource": {
"resourceType": "Binary",
"contentType": "application/json-patch+json",
"data": "base64encoded of the document below" // (b)
},
"request": {
"method": "PATCH",
"url": "Device/1835297"
}
}
]
}
PATCH
document whose base64()
goes above at (b)
[
{
"op": "test",
"path": "/meta/versionId",
"value": "x"
},
{
"op": "test",
"path": "/status",
"value": "inactive"
},
{
"op": "add",
"path": "/patient",
"value": {
"reference": "urn:uuid:abe0b81e-2aca-44c7-8469-1dc1f7301fe9",
"type": "Patient"
}
},
{
"op": "replace",
"path": "/status",
"value": "active"
}
]
I get this in return
{
"resourceType": "Bundle",
"type": "transaction-response",
// snip
"entry": [{
"response": {
"status": "201 Created",
"location": "Patient/1836280/_history/1",
"etag": "1",
"lastModified": "2021-01-22T11:50:57.291+00:00"
}
},
{
"response": {
"status": "201 Created",
"location": "CareTeam/1836281/_history/1",
"etag": "1",
"lastModified": "2021-01-22T11:50:57.291+00:00"
}
}]
}
CareTeam
has the proper reference like so
"subject": {
"reference": "Patient/1836280", // Works!
"type": "Patient"
}
But the device isn't working
"patient": {
"reference": "urn:uuid:abe0b81e-2aca-44c7-8469-1dc1f7301fe9", // should be 'Patient/1836280'
"type": "Patient"
}
René Spronk (Jan 22 2021 at 12:26):
You transaction bundle is wrong: the Bundle should contain 3 entries, currently it's just one entry with 3 resources in it. That's not allowed by Bundles. Each entry has 0..1 resource in it.
Dexter (Jan 22 2021 at 12:34):
It does, doesn't it, an array of 3 (unless I'm mistaken with the code or the formatting)?
"entry": [
{ // patient },
{ // careteam },
{ // device }
]
René Spronk (Jan 22 2021 at 13:41):
Ah yes (my XML background is to blame here). Nothing wrong with the overall structure of your Transaction.
So the issue is with your JSON patch (which I haven't played with, I've only tested FHIR patch, based of FHIR Path).
If you claim the resource type (of your PATCH) to be Binary, then the server will process it as if it were a Binary (ie a Blob, nothing to do with FHIR resource structures). As such a server won't update your 'reference', it will just patch with the literal string as present in your patch statement. Whether one would desire to have it be done in another way, well, that's a good question.
Lloyd McKenzie (Jan 22 2021 at 14:33):
PATCH doesn't really make sense for a Binary because there are very few properties you can manipulate in a Binary - just stuff in meta and the content itself.
René Spronk (Jan 22 2021 at 14:41):
The attempt is to PATCH a Patient resource, so the Bundle should probably be declaring that as the resource type instead of Binary. The documentation isn't very clear as to what resource type one should specifiy on a PATCH operation.
ryan moehrke (Jan 22 2021 at 15:45):
how is a json patch supposed to look in a transaction bundle, putting aside Dexter's problem for now do we have any guidance on that? Is it supposed to be a non-fhir document stuffed inside a bundle? packaged as a Binary like Dexter did?
does this line in the spec "Patch operations may be performed as part of Batch or Transaction Operations using the FHIRPath Patch format. "
imply that only fhirpatch can be used in batch/transactions?
Paul Church (Jan 22 2021 at 17:39):
There is no support for a json patch in a batch/transaction bundle.
Dexter (Jan 25 2021 at 04:27):
I see. So the references aren't transformed in a Bundle. How do I PATCH through a transaction in such a case? Since I'm updating resources, I don't think splitting it into 2 requests will be wise, as it might lead to inconsistencies.
If I may suggest, this section of the document led me to believe that this would work. What do you suggest I do?
Dexter (Jan 25 2021 at 04:28):
Also, apologies for the delay in my response, I need to use my Work PC for logging in.
Dexter (Jan 25 2021 at 04:29):
Dexter said:
References within a Bundle.entry.resource to another Bundle.entry.resource that is being created within the batch are considered to be non-conformant.
Does this mean that I can't create, say, a
Patient
resource and aCareTeam
at once in which theCareTeam
refers to thePatient
?
Does this mean that technically, HAPI is non-conformant?
Lloyd McKenzie (Jan 25 2021 at 05:53):
In a transaction, you have to use FHIRpath-based patch
Nothing prohibits a server from supporting batches where the actions have interdependencies - or otherwise consuming data that's non-conformant. However, HAPI shouldn't spit out batches that break the rules.
Dexter (Jan 25 2021 at 06:07):
Could you clarify what the patch doc would look like, I couldn't find the schema for this. A link to the relevant portion would be great too, thanks!
Nothing prohibits a server from supporting batches where the actions have interdependencies - or otherwise consuming data that's non-conformant.
So that means me being able to create a Patient
resource and a CareTeam
at once in a Transaction
where the CareTeam
refers to the Patient
is something that's supported by HAPI, but NOT the FHIR specification, therefore I shouldn't expect other server implementations to support this, correct?
René Spronk (Jan 25 2021 at 07:34):
Quite the opposite. All servers that support Bundles have to support this. See http://build.fhir.org/bundle.html#references
Dexter (Jan 25 2021 at 07:57):
Um, I'm a little confused in that case, could you please clarify what this means?
References within a Bundle.entry.resource to another Bundle.entry.resource that is being created within the batch are considered to be non-conformant.
Also,
Whether one would desire to have it be done in another way, well, that's a good question.
Haha yeah I think that's what I'm after right now. I'm looing at FHIRPatch, as Mr. Lloyd suggested, but I don't see a way to send that in a JSON form through JS frontend client.
René Spronk (Jan 25 2021 at 08:11):
We're talking about a Transaction bundle, right? A Batch is quite a different thing - but you're right in that my statement above I should have spoken about Transactions, not about Bundles in general.
Dexter (Jan 25 2021 at 08:13):
Yep Transaction, though I should probably read up on the differences b/w bundle and batch.
Lloyd McKenzie (Jan 25 2021 at 15:29):
You'd be sending a Parameters resource - which can be expressed in XML, JSON or RDF - just as any resource is.
Dexter (Jan 27 2021 at 04:20):
I'm not sure how to use that, I couldn't find many examples similar to what I'm trying to do, i.e, have a reference in a binary resource. Could you kindly give me an example? Thanks!
René Spronk (Jan 27 2021 at 08:12):
See https://www.hl7.org/fhir/fhirpatch.html#format for an example. There is no use of Binary when using FHIRPath based patch.
Dexter (Jan 27 2021 at 08:15):
How do I convert this to a JSON payload? Is that supported? Will references resolve too? Can I put this single fhirpatch
as one of the elements of the Bundle Transaction
's entry
?
René Spronk (Jan 27 2021 at 08:30):
All FHIR resources can be expressed as either JSON, or XML, or even some other representation formats. Representation is largely irrelevant (from a standards perspective). You can add a Parameters resource as an entry in a Transaction bundle, and given that this is a FHIR resource like any other FHIR resource, the reference should resolve (admittedly: I've never tested it with a Parameters resource, but I see no reason as to why that shouldn't work).
Dexter (Jan 27 2021 at 09:06):
Okay, thank you for that! I'll give that a go, but hapi seems to be down right now. I have an issue on the local setup which I posted here
Lloyd McKenzie (Jan 27 2021 at 15:20):
Be aware that response times may be slower this week because HL7 is having a major virtual conference (and people therefore have less time than usual)
Dexter (Jan 28 2021 at 05:39):
I understand, thank you for taking the time to respond to my queries! With support from all of you, I'm having a blast learning how to go about FHIR!
Dexter (Jan 28 2021 at 09:25):
René Spronk said:
See https://www.hl7.org/fhir/fhirpatch.html#format for an example. There is no use of Binary when using FHIRPath based patch.
I think I'm getting the hand of using FHIRPatch
. How do I test for a version of a resource before PATCH
ing it with FHIRPatch
?
I'm trying to use ifMatch
, but this doesn't seem to work. What am I missing in this?
(Without ifMatch
and Device/id
works fine, so I think I understood how to use FHIRPatch
)
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"resource": {
"resourceType": "Parameters",
"parameter": [
{
"name": "operation",
"part": [
{
"name": "type",
"valueString": "add"
},
{
"name": "path",
"valueString": "Device"
},
{
"name": "name",
"valueString": "patient"
},
{
"name": "value",
"valueReference": {
"reference": "Patient/1714653",
"type": "Patient"
}
}
]
}
]
},
"request": {
"method": "PATCH",
"url": "Device?_id=1835297",
"ifMatch": "W\"9\""
// This works though, when the above 2 lines are replaced with this,
// so I think I understand FHIRPatch
// "url": "Device/1835297",
}
}
]
}
I get the error Invalid match URL[W\"9\"] - URL has no search parameters
, which is confosing, since I think Device?_id=1835297
is supposed to mean "search for a device with so and so ID"
René Spronk (Jan 28 2021 at 10:42):
Back to the basics: does the server in question support conditional PATChes ?
Dexter (Jan 28 2021 at 11:09):
To query that, must I look under rest.resource
?
I don't see Device
under this JSON Patch search $.entry[:].resource.rest[:].resource[:].type
Am I going about this the right way?
Lloyd McKenzie (Jan 29 2021 at 05:09):
What you should see is rest.resource with conditionalUpdate=true and resource.interaction.code = patch
Dexter (Jan 29 2021 at 07:04):
This is on the public HAPI server at hapi.fhir.org
. I don't think PATCH
is there, but conditionalUpdate
is there, multiple times. I don't see Device in the rest.resource.type
though.
Dexter (Jan 29 2021 at 07:04):
So does this mean conditional patches aren't supported for the Device resource?
Lloyd McKenzie (Jan 29 2021 at 21:54):
It could. Or it could mean the CapabilityStatement isn't complete. @James Agnew ?
Dexter (Feb 01 2021 at 05:37):
Hmm... I'm stuck now. If this isn't supported, how can I achieve this?
From my basic inspection, I didn't see hapi.fhir.org
's conformance statement with PATCH
, but I think it does, since it's the de-facto implementation of the spec. What am I missing here?
I recall that conditional patched worked when I was using JSON PATCH
. Does this support also translate to FHIRPatch
?
Dexter (Feb 01 2021 at 06:36):
Lloyd McKenzie said:
In a transaction, you have to use FHIRpath-based patch
I tried this, doesn't work. As an alternative to conditional patch, I first test for the version in a JSON Patch, so if that doesn't match, the transaction should be aborted. I think it's equivalent to using ifMatch
in FHIRPatch
. Here's what I'm sending
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"resource": {
"resourceType": "Binary",
"contentType": "application/json-patch+json",
"data": "base64( [{ "op": "test", "path": "/meta/versionId", "value": "versionId"}] )"
},
"request": {
"method": "PATCH",
"url": "Device/1835297"
}
},
{
"fullUrl": "urn:uuid:abe0b81e-2aca-44c7-8469-1dc1f7301fe9",
"resource": {
"resourceType": "Patient",
"name": [
{
"use": "official",
"given": [
"Ben One"
],
"family": "Ben One"
}
],
"gender": "male",
"birthDate": "1987-01-22",
},
"request": {
"method": "POST"
}
},
{
"resource": {
"resourceType": "Parameters",
"parameter": [
{
"name": "operation",
"part": [
{
"name": "type",
"valueString": "add"
},
{
"name": "path",
"valueString": "Device"
},
{
"name": "name",
"valueString": "patient"
},
{
"name": "value",
"valueReference": {
"reference": "urn:uuid:abe0b81e-2aca-44c7-8469-1dc1f7301fe9",
"type": "Patient"
}
}
]
}
]
},
"request": {
"method": "PATCH",
"url": "Device/1835297"
}
}
]
}
This doesn't resolve the urn:uuid:xx
either,
{
"resourceType": "Device",
"id": "1835297",
// ... other data
"patient": {
"reference": "urn:uuid:abe0b81e-2aca-44c7-8469-1dc1f7301fe9",
"type": "Patient"
}
}
What am I missing here?
Lloyd McKenzie (Feb 01 2021 at 07:28):
You might try asking on #hapi Some of those most familiar with it don't monitor this stream because it's too high-volume
René Spronk (Feb 01 2021 at 07:30):
By the way, none of the available FHIR test servers implements the full spec, so one should never assume any particular server to do so.
Dexter (Feb 01 2021 at 07:46):
I see, okay.
Dexter (Feb 01 2021 at 08:43):
Okay, thank you for letting me know!
I've split into 2 topics
HAPI Docker setup
Transactions
sean zitello (Feb 26 2021 at 00:29):
IHE IT-65 ProvideDocBundle The Bundle includes DocumentManifest DocumentReference Binary. I had assumed that whenever I use "urn:uuid:..." in a 'url' typed element, it would be replaced by the server. In this case. the Binary.id / fullUrl and the DocumentReference.content.attachment match in the transsction request. The attachment value is not replaced however in the response though. That seems to indicate I need to persist the Binary first, get the id and then reference as FQ in transaction request? Is this expected behavior. Am I missing something? (R4.0)
Lloyd McKenzie (Feb 26 2021 at 05:27):
The transaction processing rules in the spec clearly say "Servers SHALL replace all matching links in the bundle, whether they are found in the resource ids, resource references, elements of type uri, url, oid, uuid, and <a href="" & <img src="" in the narrative." So it sounds like your server isn't behaving correctly. Are you hitting one of the standard reference servers?
Lloyd McKenzie (Feb 26 2021 at 05:27):
(In this case, DocumentReference.content.attachment is of type 'url', which is covered by the rule.)
Dexter (Feb 26 2021 at 10:41):
Yeah I'm hitting the public HAPI server at hapi.fhir.org
. Apologies for the delay in response, I asked in the #hapi stream as suggested. I've reported this as a bug (as suggested by Mr René Spronk) on GitHub here
sean zitello (Feb 26 2021 at 13:45):
Lloyd McKenzie said:
The transaction processing rules in the spec clearly say "Servers SHALL replace all matching links in the bundle, whether they are found in the resource ids, resource references, elements of type uri, url, oid, uuid, and <a href="" & <img src="" in the narrative." So it sounds like your server isn't behaving correctly. Are you hitting one of the standard reference servers?
HAPI R4 public is good. I have two other vendor 1 private, 1 public private instance where it fails.
Lloyd McKenzie (Feb 26 2021 at 14:35):
Where it fails, you should report a bug to whoever's running that system - and point them at the language I quoted.
Last updated: Apr 12 2022 at 19:14 UTC