Stream: implementers
Topic: Conditional Creates Transaction HAPI
Paul Barry (May 13 2016 at 00:57):
Currently testing conditional logic on the HAPI and getting some unexpected behaviour. I'm using a transaction withjust a single entry for now until I can see I am using the correct logic. In this instance I want to only 'Create' a practitioner if they dont already exist. Otherwise do nothing. So my bundle looks like this.
<Bundle xmlns="http://hl7.org/fhir"> <!-- we need to use a transaction for this type of procedure --> <type value="transaction"/> <!-- Bundle Id will be generated by Map Force on the client - this is the resource id for the bundle --> <id value="f9935843-19a2-4a1a-4016-7bea52de77f8"/> <!--Lets process patient first --> <!--We still need to include patient in the bundle for our check even though it a cut down bogus entry--> <entry> <!--Should this be provided for a Create i.e. should the adapter generate the local id (if resource not exist) or let the fhir server do it?--> <!--This is generate by Map Force and use for references. If Practitioner does not exist FHIR server should use it at Local Resource Id--> <fullUrl value="urn:uuid:47709cc7-b3ec-4abc-9d26-3df3d3d57907"/> <resource> <Practitioner xmlns="http://hl7.org/fhir"> <identifier> <use value="official"/> <!--Reuse value from CDA --> <system value="urn:oid:2.16.840.1.113883.2.4.6.3"/> <!--Reuse OIDs from CDA --> <!-- BSN identification system --> <value value="567IUI51C157"/> </identifier> <name> <use value="official"/> <family value="Heps"/> <given value="Simone"/> <suffix value="MD"/> </name> <telecom> <system value="phone"/> <value value="020556936"/> <use value="work"/> </telecom> <telecom> <system value="email"/> <value value="S.M.Heps@bmc.nl"/> <use value="work"/> </telecom> <telecom> <system value="fax"/> <value value="0205669283"/> <use value="work"/> </telecom> <address> <use value="work"/> <line value="Galapagosweg 91"/> <city value="Den Burg"/> <postalCode value="9105 PZ"/> <country value="NLD"/> <!-- ISO 3166 Codes (Countries) --> </address> <gender value="female"/> <birthDate value="1971-11-07"/> </Practitioner> </resource> <request> <!--For this entry we only want to create the practitioner based on the entry data if we dont find one --> <method value="POST"/> <url value="Practitioner"/> <!--Use DrProviderNumber Paul to add more syntax below--> <ifNoneExist value="identifier=567IUI51C157"/> </request> </entry> </Bundle>
It creates a new practitioner the first time as expected. But if I post the same transaction again I would expect it to not create a new practitioner because it already exists. On the HAPI server it will create a new practitioner each time. Is my bundle correct?
Chris Moesel (May 13 2016 at 02:15):
Based on Conditional Update in the spec, shouldn't your request
element be something more like this?
<request> <!--For this entry we only want to create the practitioner based on the entry data if we dont find one --> <method value="PUT"/> <url value="Practitioner?identifier=567IUI51C157"/> </request>
Paul Barry (May 13 2016 at 02:36):
When I try that I get an error on the Hapi server indicating a missing search parameter? However from what I understand, using PUT is when I want to either create new or update if exists already. The logic I want is to create if not exists otherwise do nothing - is that possible?
Simone Heckmann (May 13 2016 at 03:33):
Did you try Chris' suggested URL with POST?
Simone Heckmann (May 13 2016 at 03:33):
That should work...
Paul Barry (May 13 2016 at 03:46):
@Simone Heckmann are you saying I shouldn't use
<ifNoneExist value="Practitioner?identifier=567IUI51C157"/>
Chris Moesel (May 13 2016 at 13:35):
I apologize, @Paul Barry. I mis-read your original intent. I agree that what you're doing seems like it should work. Based on documentation in Bundle, I think you're right about having Practitioner
as the url value (without the query) and putting the query parameter(s) in the ifNoneExist
value (without the Practitioner?
part). Perhaps @James Agnew can chime in to confirm or deny if this functionality is implemented in HAPI.
One thing you could try (although it shouldn't make a difference) is putting the system in the query too: identifier=urn:oid:2.16.840.1.113883.2.4.6.3|567IUI51C157
James Agnew (May 13 2016 at 23:03):
Hi Paul,
Are you posting this against our public test server, or your own server? If the latter, what version of HAPI are you using?
Your bundle looks correct to me, and if I post it to our public test server it seems to do the right thing (first time it created the resource, subsequent times is did not)
Paul Barry (May 16 2016 at 02:43):
@James Agnew thanks for your response. I am using your public test server. Will include bundle again:
<Bundle xmlns="http://hl7.org/fhir"> <type value="transaction"/> <id value="f9935843-19a2-4a1a-4016-7bea52de77f8"/> <entry> <fullUrl value="urn:uuid:47709cc7-b3ec-4abc-9d26-3df3d3d57907"/> <resource> <Practitioner xmlns="http://hl7.org/fhir"> <identifier> <use value="official"/> <!--Reuse value from CDA --> <system value="urn:oid:2.16.840.1.113883.2.4.6.3"/> <!--Reuse OIDs from CDA --> <!-- BSN identification system --> <value value="567IUI51C157"/> </identifier> <name> <use value="official"/> <family value="Heps"/> <given value="Simone"/> <suffix value="MD"/> </name> <telecom> <system value="phone"/> <value value="020556936"/> <use value="work"/> </telecom> <telecom> <system value="email"/> <value value="S.M.Heps@bmc.nl"/> <use value="work"/> </telecom> <telecom> <system value="fax"/> <value value="0205669283"/> <use value="work"/> </telecom> <address> <use value="work"/> <line value="Galapagosweg 91"/> <city value="Den Burg"/> <postalCode value="9105 PZ"/> <country value="NLD"/> <!-- ISO 3166 Codes (Countries) --> </address> <gender value="female"/> <birthDate value="1971-11-07"/> </Practitioner> </resource> <request> <!--For this entry we only want to create the practitioner based on the entry data if we dont find one --> <method value="POST"/> <url value="Practitioner"/> <!--Use DrProviderNumber Paul to add more syntax below--> <ifNoneExist value="Practitioner?identifier=567IUI51C157"/> </request> </entry> </Bundle>
When I post the transaction the first time I get the following
<Bundle xmlns="http://hl7.org/fhir"> <id value="49f13866-319d-429a-8bab-1978951b6912"/> <type value="transaction-response"/> <link> <relation value="self"/> <url value="http://fhirtest.uhn.ca/baseDstu2"/> </link> <entry> <response> <status value="201 Created"/> <location value="Practitioner/69207/_history/1"/> <etag value="1"/> <lastModified value="2016-05-15T22:34:56.049-04:00"/> </response> </entry> </Bundle>
When I post the second time I get the same with a new logical id
<Bundle xmlns="http://hl7.org/fhir"> <id value="73614efd-e180-4c31-9695-e863931f367e"/> <type value="transaction-response"/> <link> <relation value="self"/> <url value="http://fhirtest.uhn.ca/baseDstu2"/> </link> <entry> <response> <status value="201 Created"/> <location value="Practitioner/69209/_history/1"/> <etag value="1"/> <lastModified value="2016-05-15T22:36:19.942-04:00"/> </response> </entry> </Bundle>
Paul Barry (May 16 2016 at 02:46):
Thanks @Chris Moesel . I did try that too but same result. Strangely when I search by 'Practitioner?identifier=567IUI51C157' it returns all the practitioners so the search syntax is working.
James Agnew (May 16 2016 at 14:17):
How are you sending this bundle in?
I took the contents of your bundle and pasted it into a file called transaction_bundle.xml
then used curl to send it to the public server with the following command:
curl -v -X POST -H "Content-type: application/xml+fhir" --data @transaction-bundle2.xml http://fhirtest.uhn.ca/baseDstu2/
The server correctly rejects it because the conditional has several matches:
{ "resourceType":"OperationOutcome", "issue":[ { "severity":"error", "code":"processing", "diagnostics":"Failed to CREATE resource with match URL \"Practitioner?identifier=567IUI51C157\" because this search matched 5 resources" } ] }
Paul Barry (May 16 2016 at 22:55):
I paste the xml into the bundle textbox on the hapi landing page and click the 'transaction' button
However even when I choose a new identifier it still creates even when the condition has a single matach
Simone Heckmann (May 17 2016 at 17:30):
Hi, I just checked my connectathon stuff and realized I am using conditional update mostly, which works perfectly.
This bundle:
<Bundle xmlns="http://hl7.org/fhir"> <id value="20160517191157" /> <type value="transaction" /> <entry> <fullUrl value="urn:uuid:4bf66899-a14a-46ed-5346-9f49e7df7c87" /> <resource> <Patient> <meta> <tag> <code value="CLOVERLEAF" /> </tag> </meta> <identifier> <use value="usual" /> <type> <coding> <system value="http://hl7.org/fhir/identifier-type" /> <code value="MR" /> </coding> </type> <system value="http://www.ghh.org/identifiers" /> <value value="presentation3" /> <assigner> <display value="TCPAS" /> </assigner> </identifier> <name> <use value="official" /> <family value="CondRef" /> <given value="Guy" /> </name> <telecom> <system value="phone" /> <value value="277543" /> <use value="home" /> </telecom> <gender value="female" /> <birthDate value="1928-05-24" /> <address> <line value="22 Stable Road" /> <city value="Whitstable" /> <state value="Kent" /> <country value="CR5 1EL" /> </address> <contact> <relationship> <coding> <system value="http://hl7.org/fhir/patient-contact-relationship" /> <code value="parent" /> </coding> </relationship> <name> <family value="CondRef" /> <given value="Dad" /> </name> </contact> </Patient> </resource> <request> <method value="PUT" /> <url value="Patient?identifier=http://www.ghh.org/identifiers|presentation3" /> </request> </entry> <entry> <fullUrl value="urn:uuid:ff89de6d-e4b2-4c6d-6f8d-929b0332a7df" /> <resource> <Encounter> <meta> <tag> <code value="CLOVERLEAF" /> </tag> </meta> <identifier> <use value="usual" /> <type> <coding> <system value="http://hl7.org/fhir/identifier-type" /> <code value="MR" /> </coding> </type> <system value="http://general-hospital.co.uk/Identifiers" /> <value value="presentation1" /> <assigner> <display value="GENHOS" /> </assigner> </identifier> <status value="in-progress" /> <class value="inpatient" /> <patient> <reference value="urn:uuid:4bf66899-a14a-46ed-5346-9f49e7df7c87" /> <display value="CondRef, Guy(*24.05.1928)" /> </patient> <period> <start value="2015-05-02T09:00:00+01:00" /> </period> </Encounter> </resource> <request> <method value="PUT" /> <url value="Encounter?identifier=http://general-hospital.co.uk/Identifiers|presentation1" /> </request> </entry> </Bundle>
returns
<Bundle xmlns="http://hl7.org/fhir"> <id value="83d18d6a-f73c-4e61-9740-635defd91eec"/> <type value="transaction-response"/> <link> <relation value="self"/> <url value="http://fhirtest.uhn.ca/baseDstu2"/> </link> <entry> <response> <status value="201 Created"/> <location value="Patient/69559/_history/1"/> <etag value="1"/> <lastModified value="2016-05-17T13:17:55.563-04:00"/> </response> </entry> <entry> <response> <status value="201 Created"/> <location value="Encounter/69560/_history/1"/> <etag value="1"/> <lastModified value="2016-05-17T13:17:55.592-04:00"/> </response> </entry> </Bundle>
the first time I send it and
<Bundle xmlns="http://hl7.org/fhir"> <id value="cffd1412-3192-44fb-bdc9-35c5f336e900"/> <type value="transaction-response"/> <link> <relation value="self"/> <url value="http://fhirtest.uhn.ca/baseDstu2"/> </link> <entry> <response> <status value="200 OK"/> <location value="Patient/69559/_history/2"/> <etag value="2"/> <lastModified value="2016-05-17T13:18:21.271-04:00"/> </response> </entry> <entry> <response> <status value="200 OK"/> <location value="Encounter/69560/_history/2"/> <etag value="2"/> <lastModified value="2016-05-17T13:18:21.312-04:00"/> </response> </entry> </Bundle>
the second time, so no douplicates created
Consecutively I changed the Method to POST and the url-Parameter to ifNoneExist and sent the same Bundle again.
Result:
<Bundle xmlns="http://hl7.org/fhir"> <id value="3bdb23da-4911-41f0-9ecf-517e70f33aa3"/> <type value="transaction-response"/> <link> <relation value="self"/> <url value="http://fhirtest.uhn.ca/baseDstu2"/> </link> <entry> <response> <status value="200 OK"/> <location value="Patient/69559/_history/2"/> <etag value="2"/> <lastModified value="2016-05-17T13:23:11.504-04:00"/> </response> </entry> <entry> <response> <status value="200 OK"/> <location value="Encounter/69560/_history/2"/> <etag value="2"/> <lastModified value="2016-05-17T13:23:11.504-04:00"/> </response> </entry> </Bundle>
So: no update and no duplicates! Exactly as expected.
Searching for /Encounter?identifier=http://general-hospital.co.uk/Identifiers|presentation3
still returns only one result.
However, I don't see the difference to what you are trying to do.
I used PostMan btw...
Simone Heckmann (May 17 2016 at 17:35):
@Paul Barry I think HAPI get's confused because you're mixing conditional update parameters with conditional creates.
You should have either
method = PUT
url = condition
OR
method = POST
ifNoneMatch = condition
Currently you're sending both url AND ifNoneMatch at the same time. Maybe that's the problem.
Simone Heckmann (May 17 2016 at 17:44):
though I can's even point at the place in the specification, where this is explicitly stated. I just always did it that way...
There's no invariant stating that you can't use both at the same time.
If it is in fact the case, that you're only supposed to use EITHER url OR ifNoneMatch, then I guess the spec needs to be more verbose about it.
@Grahame Grieve @James Agnew ...?
Grahame Grieve (May 17 2016 at 19:38):
the spec doesn't say anything about using url for conditional create
James Agnew (May 17 2016 at 19:46):
I'm confused... Paul's bundle looks like it's doing a normal conditional create to me?
<request> <method value="POST"/> <url value="Practitioner"/> <ifNoneExist value="Practitioner?identifier=567IUI51C157"/> </request>
Grahame Grieve (May 17 2016 at 19:47):
hmm I should have read more carefully then?
James Agnew (May 17 2016 at 19:48):
I'm questioning Simone's statement:
I think HAPI get's confused because you're mixing conditional update parameters with conditional creates.
James Agnew (May 17 2016 at 19:49):
as far as I can see, the bundle that Paul is sending looks 100% correct... but he seems to get different behaviour when he posts it to what I get, so I feel like I'm missing something.
Simone Heckmann (May 17 2016 at 20:02):
Yes, I just postmanned Barry's Bundle to HAPI and I don't get duplicates either. Funny though, that I - for some reason - never use "url" in conditional creates and neither yours nor Grahame's server seem to care :)
James Agnew (May 17 2016 at 20:05):
Heh- we're both being nice, since url is actually 1..1
in Bundle.entry.request
:)
James Agnew (May 17 2016 at 20:06):
I wonder what would happen if you put a conditional URL there... In theory the server should tell you to take a hike, but it might not actually do that.
Simone Heckmann (May 17 2016 at 20:06):
@Grahame Grieve : it seems a little strange that when posting a transaction with two entries that, due to the given condition, remain both unchanged, the response looks like this:
<?xml version="1.0" encoding="UTF-8"?> <Bundle xmlns="http://hl7.org/fhir"> <id value="92a864ac-8e0f-4e38-8592-b2f6ce909d"/> <type value="transaction-response"/> <entry/> <entry/> </Bundle>
Simone Heckmann (May 17 2016 at 20:09):
(deleted)
Simone Heckmann (May 17 2016 at 20:14):
oops. I must have never validated my Bundle, just the resources :-/
Grahame Grieve (May 17 2016 at 21:27):
well, if you got that from my server it's certainly an error
Paul Barry (May 18 2016 at 02:21):
@James Agnew @Simone Heckmann have you tried posting the bundle using the transaction textbox on the Hapi landing page? http://fhirtest.uhn.ca/#
I will have a go with POSTMan tonight and see what happens. Cheers
Simone Heckmann (May 18 2016 at 08:37):
Interesting. It seems indeed to be a textbox issue. I wonder how that happens!?
Paul Barry (May 18 2016 at 22:15):
@James Agnew @Simone Heckmann I tried my bundle using POSTman and it worked so there must be something wroing with the transaction textbox feature on the hapi landing page. I also confirmed that I must use the syntax Simone specified for conditional creates vs updates i.e.
You should have either method = PUT url = condition OR method = POST ifNoneMatch = condition
Paul Barry (May 19 2016 at 01:11):
(deleted)
James Agnew (May 19 2016 at 17:36):
Ahhhh ok, so it sounds like this is an issue with the Test Web UI as opposed to the server. That makes sense, I hadn't tested that.
When you're in the UI, are you targeting the DSTU2 endpoint or the DSTU3?
Last updated: Apr 12 2022 at 19:14 UTC