Prerequisites • Exercise 0 • Exercise 1 • Exercise 1.1 • Exercise 2 • Exercise 3 • Exercise 4 • Exercise 5 • Exercise 6 • Exercise 7
This exercise introduces a new scenario which will serve as an example on how User Tasks, resource download and Task Output Parameters
may be utilized. The scenario is a voting process where one DSF instances of the tutorial setup will send a binary question (yes/no) to the other instances and itself.
The question can be set when starting the voting process. The question will then be answerable through a QuestionnaireResponse resource on the instance's DSF FHIR server.
The answer then gets sent back to the instance which initiated the voting process. This exercise will focus on User Tasks and Task Output Parameters.
The scenario comes with a skeleton including two BPMN models. One for orchestrating the voting process called exampleorg_votingProcess found in voting-process.bpmn and the subprocess which handles the vote itself found in vote.bpmn.
It also includes most of the Java implementation for both processes and the required FHIR resources. Your task will be to fill in the parts concerning the User Task
and Task Output Parameters.
In order to solve this exercise, you should have solved exercise 6 and read the topics on User Tasks, Questionnaire and QuestionnaireResponse and adding Task Output Parameters.
Solutions to this exercise are found on the branch solutions/exercise-7. The skeleton can be found on the branch skeleton/exercise-7. It contains an entirely new process with missing pieces that will be added as part of the exercise tasks.
You may checkout the skeleton branch and start working from there. You may also merge the skeleton branch into the branch you were working on so far, at your own risk.
-
The StructureDefinition
task-start-voting-process.xmldescribes the Task resource which starts the voting process. It already has an input parameter calledbinary-questionwhich stores the question you want to pose to all DSF instances in the network. When the entire voting process is finished, we would like to see all the voting results of the other instances listed as output parameters in this resource.
Add a Task Output Parameter calledvoting-result:-
This parameter stores the voting result of one instance as either
yes,noortimeout. This can be achieved by using aCodingas the type forTask.output.value[x]. The codings for this are already provided by the CodeSystemvoting-processlocated intutorial-process/src/main/resources/fhir/CodeSystem/voting-process.xmland included in a ValueSet calledvoting-resultslocated intutorial-process/src/main/resources/fhir/ValueSet/voting-results.xml.Don't know how to include the coding?
Define the
Task.output.value[x]element for your Output Parameter slice with a type ofCoding.XML Example
<element id="Task.output:example-output.value[x]"> <path value="Task.output.value[x]"/> <max value="1"/> <type> <code value="Coding"/> </type> </element>
Define the CodeSystem of the Coding using the URL of the
voting-processCodeSystem.XML Example
<element id="Task.output:example-output.value[x].system"> <path value="Task.output.value[x]"/> <min value="1"/> <max value="1"/> <fixedUri value="http://example.org/fhir/CodeSystem/voting-process"/> </element>
Define the values that are allowed for the Coding by binding it to the
voting-resultsValueSet using a binding strength ofrequired.XML Example
<element id="Task.output:example-output.value[x].code"> <path value="Task.output.value[x].code"/> <min value="1"/> <max value="1"/> <binding> <strength value="required"/> <valueSet value="http://example.org/fhir/ValueSet/voting-results"/> </binding> </element>
-
It can appear any number of times. Define the cardinality as
0..* -
It needs to include information on which instance did the voting. Use the extension
extension-voting-resultfound intutorial-process/src/main/resources/fhir/StructureDefinition/extension-voting-result.xmlDon't know how to include the extension?
Create a slice for
Task.output:example-output.extension. AddExtensionas the value forTask.output:example-output.extension.type.codeand add the URL of the extension as the value forTask.output:example-output.extension.type.profile.XML Example
<element id="Task.output:example-output.extension:my-extension"> <path value="Task.output.extension"/> <sliceName value="example-output"/> <min value="1"/> <max value="1"/> <type> <code value="Extension"/> <profile value="http://example.org/fhir/StructureDefinition/my-extension"/> </type> </element>
-
-
In the next steps, we will create the part of the process where a user has to interact with a QuestionnaireResponse in the DSF FHIR server web UI to answer the question defined in the input parameter of
task-start-voting-process.xml. Create a Questionnaire intutorial-process/src/main/resources/fhir/Questionnaire/user-vote.xmlcalleduser-vote. Don't forget to register it in the Process Plugin Definition for thevoteprocess.Don't know how the Questionnaire should look like?
Check out the template again. Don't forget changing the URL.
- Add an item with linkId
binary-questionand typedisplay. - Add an item with linkId
voteand typeboolean.
- Add an item with linkId
-
We now have a Questionnaire resource that can be referenced in the BPMN model's User Tasks. If referenced, the DSF will take this Questionnaire as a template to create the QuestionnaireResponse that can be answered by a user in the DSF FHIR server web UI.
Add a User Task tovote.bpmnlocated intutorial-process/src/main/resources/bpe/vote.bpmn:- The User Task should be inserted between the Exclusive Gateway and the
Save User VoteService Task. The connection from the Exclusive Gateway requires a Condition element with typeExpressionandCondition Expressionwith value${userVote}. - The Questionnaire resource is referenced by providing a
Form keyattribute with the value of the Questionnaire URL you created in the previous step appended by the version placeholder|#{version}. This option is found underFormsand typeEmbedded or External Task Forms.
- The User Task should be inserted between the Exclusive Gateway and the
-
The QuestionnaireResponse that is automatically created will copy its items from the template Questionnaire. This means we need a way to set the
item.textelement of thebinary-questionitem you created in the previous step, dynamically. This mechanism is provided by Task Listeners. Create a User Task Listener intutorial-process/src/main/java/dev/dsf/process/tutorial/listenerfor the User Task you added in the previous step:- The new Java class needs to inherit from
DefaultUserTaskListener - Override
beforeQuestionnaireResponseCreateand set the text of the QuestionnaireResponse item with linkIdbinary-questionto the value of the Start Task's input parameter with namebinary-question - Register the listener as a Spring Bean.
UserTaskListenersare anActivity.
- The new Java class needs to inherit from
Execute a maven build of the dsf-process-tutorial parent module via:
mvn clean install -Pexercise-7
Verify that the build was successful and no test failures occurred.
To verify the exampleorg_votingProcess can be executed successfully, we need to deploy them into DSF instances and execute the exampleorg_votingProcess. The maven install build is configured to create a process jar file with all necessary resources and copy the jar to the appropriate locations of the docker dev setup.
Again, you may decide to authenticate and start the process via the certificate or the Keycloak user Tyler Tester with username test and password test. You can find the client certificate
in .../dsf-process-tutorial/browser-certs/dic/dic-client.p12 (password: password).
-
Start the DSF FHIR server for the
dic.dsf.testorganization in a console at location.../dsf-process-tutorial/dev-setup:docker compose up dic-fhirVerify the DSF FHIR server started successfully at https://dic/fhir.
-
Start the DSF BPE server for the
dic.dsf.testorganization in a second console at location.../dsf-process-tutorial/dev-setup:docker compose up dic-bpeVerify the DSF BPE server started successfully and deployed the
exampleorg_votingProcess. -
Start the DSF FHIR server for the
cos.dsf.testorganization in a third console at location.../dsf-process-tutorial/dev-setup:docker compose up cos-fhirVerify the DSF FHIR server started successfully at https://cos/fhir.
-
Start the DSF BPE server for the
cos.dsf.testorganization in a fourth console at location.../dsf-process-tutorial/dev-setup:docker compose up cos-bpeVerify the DSF BPE server started successfully and deployed the
exampleorg_votingProcess. -
Start the DSF FHIR server for the
hrp.dsf.testorganization in a fifth at location.../dsf-process-tutorial/dev-setup:docker compose up hrp-fhirVerify the DSF FHIR server started successfully at https://hrp/fhir.
-
Start the DSF BPE server for the
hrp.dsf.testorganization in a sixth console at location.../dsf-process-tutorial/dev-setup:docker compose up hrp-bpeVerify the DSF BPE server started successfully and deployed the
exampleorg_votingProcess. -
Start the
exampleorg_votingProcessby posting a specific FHIR Task resource to the DSF FHIR server of thedic.dsf.testorganization using either cURL or the DSF FHIR server's web interface. Check out Starting A Process Via Task Resources again if you are unsure. Make sure to populate the Input Parameters.Verify that the FHIR Task resource was created at the DSF FHIR server and the
exampleorg_votingProcesswas executed. To do this, navigate to https://dic/fhir/QuestionnaireResponse?_sort=-_lastUpdated&status=in-progress. There should be a QuestionnaireResponse resource with statusin-progressbased on a Questionnaire resource with URLhttp://example.org/fhir/Questionnaire/user-vote. Click on the QuestionnaireResponse, answer the question and pressSubmit. Navigate to https://dic/fhir/Task?_sort=-_lastUpdated and find the latest Task resource with message-namestartVotingProcess. It should have a status ofcompleted. Clicking on the Task resource redirects to the detailed Task view and three Output Parameters should now be present. Each one describes the voting result of an Organization that responded in thevoteprocess. The responses fromcos.dsf.testandhrp.dsf.testhave a randomly generated response, but they should not have a value oftimeout. Depending on whether you completed the QuestionnaireResponse in time, the output fordic.dsf.testshould show your answer ortimeout.
Prerequisites • Exercise 0 • Exercise 1 • Exercise 1.1 • Exercise 2 • Exercise 3 • Exercise 4 • Exercise 5 • Exercise 6 • Exercise 7