Sure! FHIRCraft is built using InterSystems IRIS for Health and works through an interoperability production.

When you send a request (e.g. from the web UI), it goes through a REST service that transforms the input JSON into an IRIS message. From there, a business process handles the generation logic. Depending on the configuration, it can reuse existing resources from a FHIR repository or generate new ones.

The generated resources (like Patient, Observation, etc.) are optionally posted back to a FHIR server — either the default IRIS repository or any external one via REST.

It’s modular and easy to extend with new resource types. If you're curious, I wrote a short technical walkthrough here 😉

I reuse object that I get on first transformation and I transform it to another object, after a call.

This is the BPL that I use:

Class test.bp.TestProcess Extends Ens.BusinessProcessBPL
{

Storage Default
{
<Type>%Storage.Persistent</Type>
}

/// BPL Definition
XData BPL [ XMLNamespace = "http://www.intersystems.com/bpl" ]
{
<process language='objectscript' request='Ens.Request' response='Ens.Response' height='2100' width='2000' >
<context>
<property name='dataRsp' type='test.msg.GetDataResponse' instantiate='0' />
<property name='patient' type='HS.FHIR.DTL.vR4.Model.Resource.Patient' instantiate='0' />
<property name='fhirRsp' type='test.msg.SendResponse' instantiate='0' />
<property name='otherPatient' type='HS.FHIR.DTL.vR4.Model.Resource.Patient' instantiate='0' />
</context>
<sequence xend='200' yend='800' >
<code name='LOGASSERT 1' xpos='200' ypos='250' >
<![CDATA[ $$$LOGASSERT("1. Get data")]]>
</code>
<call name='GetData' target='TestBo' async='0' xpos='200' ypos='350' >
<request type='test.msg.GetDataRequest' >
</request>
<response type='test.msg.GetDataResponse' >
<assign property="context.dataRsp" value="callresponse" action="set" languageOverride="" />
</response>
</call>
<code name='LOGASSERT 2' xpos='335' ypos='600' >
<![CDATA[ $$$LOGASSERT("2. Transform to FHIR")]]>
</code>
<transform name='Transform 1' class='test.dtl.DataToPatient' source='context.dataRsp' target='context.patient' xpos='335' ypos='700' />
<code name='LOGASSERT 3' xpos='335' ypos='800' >
<![CDATA[ $$$LOGASSERT("3. Send to FHIR Repo 1")]]>
</code>
<call name='Send to FHIR Repo 1' target='TestBo' async='0' xpos='335' ypos='900' >
<request type='test.msg.SendRequest' >
<assign property="callrequest" value="##class(test.Util).generatePostFHIRReq(context.patient)" action="set" languageOverride="" />
</request>
<response type='test.msg.SendResponse' >
</response>
</call>
<code name='LOGASSERT 4' xpos='470' ypos='1150' >
<![CDATA[ $$$LOGASSERT("4. Transform to FHIR again (for other repo)")]]>
</code>
<!-- <transform name='REPEAT: Transform 1' class='test.dtl.DataToPatient' source='context.dataRsp' target='context.patient' xpos='335' ypos='700' /> -->
<transform name='Transform 2' class='test.dtl.DataToOtherPatient' source='context.patient' target='context.otherPatient' xpos='470' ypos='1350' />
<code name='LOGASSERT 5' xpos='470' ypos='1450' >
<![CDATA[ $$$LOGASSERT("5. Send to FHIR Repo 2")]]>
</code>
<call name='Send to FHIR Repo 2' target='TestBo' async='0' xpos='470' ypos='1550' >
<request type='test.msg.SendRequest' >
<assign property="callrequest" value="##class(test.Util).generatePostFHIRReq(context.otherPatient)" action="set" languageOverride="" />
</request>
<response type='test.msg.SendResponse' >
</response>
</call>
</sequence>
</process>
}

}

There is a commented line. If I activate this line (basically, repeat first transformation), then everything works.

The generatePostFHIRReq method:

ClassMethod generatePostFHIRReq(fhir As HS.FHIR.DTL.vR4.Model.Base.DomainResource) As test.msg.SendRequest
{
	#dim fhirReq As test.msg.SendRequest
	
	set fhirReq = ##class(test.msg.SendRequest).%New()
	set fhirReq.url = "/"_fhir.resourceType
	set fhirReq.body = ##class(%Stream.GlobalCharacter).%New()
	do fhirReq.body.Write(fhir.ToJSON().Read())
	
	return fhirReq
}

What I need is to send a FHIR resource to 2 different FHIR repositories. And for the second one I need to change some properties from de first transformation. I want to reuse the object obtained in first transformation, because sometimes the resource fot both FHIR repositories is the same.

That property doesn't exists in the class you are using as context. But in the rule editor, General tab, you have a section called Temporary Variables, you can create there, and reference it with @<name> in the rule. In your case, your assing will be:

assing @Namespace = Piece(AlertRequest.SourceConfigName,"|")

Here is the documentation:

Temporary Variables

User-specified temporary variables, which you can use in the rule definition. The variables must be separated by commas, for example:

FreeShippingValue,ShipMethod,PremierMember

You can reference a temporary variable in a rule definition by preceding the variable name with the @ (at sign) character, for example, @FreeShippingValue. You cannot use temporary variables outside the rule definition. To pass information to a transformation, you can instead use the RuleUserData property. For more information, see Selecting the Transformation and Target of a Send Action.

I have been testing this new UI and, like I said in this post, as a developer, changes for us are very difficult, so, I apologize for my complaints, but here they are:

  • I think the UI has too much information and elements are too small. Nowadays we have big screens, and there is a lot of space, but having all elements too close makes very difficult to see anything clearly.
  • Everything has the same colour, it's difficult to distinguish elements, menus, etc.
  • In the current version, when a production or an element is ON, you can see it very easy. But now, at least in my case, I can't see when an element is active, or disabled.
  • The right menu, for the settings, having white background and everything together, makes difficult to see where a configuration starts and where it ends. The same with dropdown menus, they are white, and they blurs into the background

I know that a change is needed, and I will adapt myself. But I think that with a few little improvements, this new UI can be a very good tool for all of us 😊

Totally agree. One of the points that botherer me was the small size of all the elements, and the same colours in all the interface. I have the same opinion: less is more. And I think the new UI has too much information.

Like Jeffrey, I can't understand the rename of Services and Operations. And I don't understand neither why now you can disable or stop an element (maybe this option existed before, but I didn't realize until know 😅).

There are other points that I don't like:

  • I can't see when a production is ON or not. Neither the elements inside the production. In the current version, you can see this with strong colours, but now, at least in my case, I can't see it
  • In right menu, I can't distinguish configurations. They are all with white background, and too together, so I can't see when a config starts and when ends. The same happens with dropdown menus. They are white too, so it's difficult to see things correctly.

As a developer, changes are difficult to me, but I know that they are necessary. I'm not against this change, but I think with a few little improvements, it would be much better.

I have checked that question, but I don't understand what happens.

Finally I have used this instruction "openssl rsautl -in fileIn.txt -out fileOut-enc.txt -pubin -inkey public.key -encrypt" using $ZF(-100) and having OpenSSL installed on the server and it works.

I want to do it with Encryption methods, there must be a way to do this with COS and not using shell instructions, right?

Thank you very much for your answer. I don't know what algorithm uses openssl_public_encrypt.

I've tried this:

set json = "{""api_key"":""XXXXX"", ""id"":""1""}"
set file = ##class(%FileCharacterStream).%New()
set file.Filename = "public.key"
set key = file.Read(file.Size) 
set jsonEncrypt = $System.Encryption.RSAEncrypt(json, key)

But it doesn't work, it returns an empty string. I try to see the error using RSAGetLastError() and I don't get anything. The public.key has this format:

-----BEGIN PUBLIC KEY-----
......
......
......
......
-----END PUBLIC KEY-----

The line breaks are LF and it is in UTF-8. What format should the public key be in order to work in Ensemble? I am doing something wrong?