Marc Mundt · Feb 24, 2021 go to post

Quick example:

Class Demo.FunctionSet Extends Ens.Util.FunctionSet
{

ClassMethod SendRequestToHTTPOp(arg1 as %String, arg2 as %String) as %String {
    if '$D(%Ensemble("%Process")) {
        write "This doesn't work in DTL test mode",!
        quit "OOPS"
    } else {
        #dim bp as Ens.BusinessProcess

        set req = ##class(Ens.StringRequest).%New()
        
        set req.StringValue=arg1_"^"_arg2

        set bp=%Ensemble("%Process")
        set tSC=bp.SendRequestSync("My.HTTP.Operation",req,.resp)
        
        if $$$ISERR(tSC) {
            // Oops... error!
        }
        
        quit "SEND SOMETHING BACK TO WHATEVER CALLED US"
    }
}

}
Marc Mundt · Feb 23, 2021 go to post

Here's a sample. The resulting URL is "/some-url?PNo=12345&PMsg=this%20is%20my%20pager%20message"

Method SendMsg(pRequest As Ens.StringRequest, Output pResponse As Ens.Response) As %Status
{
    set tFormVarNames="PNo,PMsg"
    
    set tPNo = "12345"
    set tPMsg = "this is my pager message"
    
    set tSC=..Adapter.Get(.tHttpResponse, tFormVarNames, tPNo, tPMsg)

    Quit $$$OK
}
Marc Mundt · Feb 18, 2021 go to post

A visual trace URL takes the form of:

EnsPortal.VisualTrace.zen?SESSIONID=12818

You'll need to run some queries (once in the router namespace and once in the edge namespace) to find the session ID that corresponds to your control ID.
You can find messages with that control id by querying the search table.
First you need to get the search table property ID for the MSHControlID. Change the value of ClassExtent to match whatever your local search table class is if you're not using the default:

SELECT PropId from Ens_Config.SearchTableProp WHERE ClassExtent='EnsLib.HL7.SearchTable' AND Name='MSHControlID'

Let's say that returns a PropId of 1

You can then query the search table for the control ID you're looking for where PropValue is the control id. If you have a custom search table you'll need to use your custom table name here instead of the default EnsLib_HL7.SearchTable:

SELECT DocId FROM EnsLib_HL7.SearchTable WHERE PropId=1 AND PropValue='123456789'

This gives you the ID for the message body. Let's say it returned a DocId of 98765. You can then query the message header table to get the session ID that that message body belongs to:

SELECT DISTINCT(SessionId)
FROM Ens.MessageHeader WHERE MessageBodyID = 98765

Keep in mind that the URL for the Visual Trace could change in future versions, so you're doing this at your own risk.

Marc Mundt · Feb 16, 2021 go to post

<strong> works as well:

Parameter MYMARKUP = "<strong>bold</strong><br/>not-bold";
Marc Mundt · Feb 16, 2021 go to post

The following sample works for me. HTML rendering capabilities are limited by what Apache FOP can handle.

Class test.ZenReportItemHtml Extends %ZEN.Report.reportPage
{

Parameter DEFAULTMODE = "pdf";

Parameter MYMARKUP = "<div style='font-weight:bold'>bold</div><br/><div>not-bold</div>";

XData ReportDefinition [ XMLNamespace = "http://www.intersystems.com/zen/report/definition" ]
{
<report xmlns="http://www.intersystems.com/zen/report/definition" name="Test" runonce="true">
     <element name="MyMarkup" escape="html" expression="..#MYMARKUP" />
</report>
}

XData ReportDisplay [ XMLNamespace = "http://www.intersystems.com/zen/report/display" ]
{
<report xmlns="http://www.intersystems.com/zen/report/display" name="Test">     
    <document width="8.5in" height="11in" marginLeft="1.25in"
      marginRight="1.25in" marginTop="1.0in" marginBottom="1.0in">
    </document>
    <body>
        <item field="MyMarkup" copyhtml="true" />
     </body>
 </report>
}

}
Marc Mundt · Jan 29, 2021 go to post

I suspect that some of the binary bytes are getting converted to UTF-8, and this is what the "u" option in the sixth argument of %WriteJSONStreamFromObject specifies.

You can try removing the "u" and see if that helps, but even if it does I believe you will find other problems because JSON isn't meant to carry raw binary data. Generally binary data is base 64 encoded when putting it in JSON.

One example of the problem with binary data is that the value of binario needs to be enclosed in quotes "". But the binary data could include a byte which is the same code as a quote, which would cause the JSON recipient to think that the value of binario has ended.

My suggestion is to base 64 encode the binary data.

Marc Mundt · Jan 28, 2021 go to post

You are first copying the binary content into objetoSalida.informacion, which is a %String. Then you write the %String into objetoSalida.binario which is a %Stream.GlobalBinary.

Why not just make objetoSalida.binario a %String?

Marc Mundt · Jan 28, 2021 go to post

No, you should only stop a process using the IRIS process management tools unless instructed otherwise by the WRC.

Marc Mundt · Jan 27, 2021 go to post

In Studio, go to File -> Change Namespace


In the Cache Connection Manager window, click "Connect"

In the Server Connection window, select the same server and click "OK"

Here you can untick "Remember Password" and login again

Marc Mundt · Jan 25, 2021 go to post

You were on the right track with %WriteJSONFromObject(), but you'll want to use %WriteJSONStreamFromObject() instead. I don't see what purpose the Body property in your request class serves. You can just create a stream object variable instead.

set myTempStream=##class(%Stream.GlobalCharacter).%New()
set tSC=##class("%ZEN.Auxiliary.altJSONProvider").%WriteJSONStreamFromObject(.myTempStream, pRequest)
if $$$ISERR(tSC) {
    quit tSC
}

...then later:

Set tSC=..Adapter.PostURL(tURL,.tHttpResponse, , myTempStream)
Marc Mundt · Jan 20, 2021 go to post

A pool size of 1 is the recommendation when you need to maintain FIFO (process all messages strictly in the sequence that they arrived). Going above 1 is fine if FIFO isn't required.

Each additional pool job will result in an additional OS-level process, which adds a little bit of memory usage. How much CPU is used by each process depends on how much work the operation is doing. Essentially, changing pool size from 1 to 2 has the same resource impact as adding another identical business operation.

The max possible pool size depends on lots of factors. I would suggest starting small (2? 4?), see how that affects the queue, and increase accordingly. Having a pool size of 10, for instance, isn't likely to cause performance or resource problems unless your operation is doing something crazy. If you start getting into a pool size of dozens you might want to take a closer look with the WRC. One of your main limitations might be how many concurrent connections System A allows you to make.

Marc Mundt · Jan 20, 2021 go to post

Check the settings on the business operation -- you should set the Pool Size > 1. This controls how many processes the operation uses to process requests.

Marc Mundt · Jan 20, 2021 go to post

Edit: Oops... I see Jeff Drumm already nailed this!

The best way to do this is to define your own custom utility function (which is just a class method). Your custom function will then appear in the function list in the DTL editor along side the standard functions.

Marc Mundt · Jan 19, 2021 go to post

Can the customer provide you with a sample XML file?
If not, you can try something like this online tool which accepts an XSD file and generates a sample XML document with fake data according to the XSD schema.
Demo.HL7.MsgRouter.Schema:ORM_O01 really isn't applicable to your use case. Not worth spending your time on it.

Marc Mundt · Jan 19, 2021 go to post

$this is a reference to the currently executing DTL. We need a reference to the BP that's calling the DTL.
Code action in DTL

 set ^zmm("$this")=$this
 set ^zmm("%Ensemble(""%Process"")")=%Ensemble("%Process")
TESTING>zw ^zmm
^zmm("$this")="Demo.DTL.ChainTest1"
^zmm("%Ensemble(""%Process"")")="7@EnsLib.HL7.MsgRouter.RoutingEngine"
Marc Mundt · Jan 15, 2021 go to post

No worries, it's always hard to understand from a forum post how far along someone is with their project.

Have you been given any sample XML files that adhere to the schema? If so, you can just copy the XML into the test tool window. If you do this, does it work?

One other question: what version of Ensemble or HealthShare are you using?

Marc Mundt · Jan 15, 2021 go to post

It looks like the ENSDEMO namespace doesn't have an example for XML v-docs.

The basic steps are:
- Import an XSD (XML schema) for the document format you need to work with:
https://docs.intersystems.com/healthconnectlatest/csp/docbook/Doc.View…
- In your DTL, select XML as the Source Type and for Source Document Type select the schema that you just imported
- The DTL editor will use the imported schema to display a document structure that you can use to visually build your mappings
At this point you can paste into the testing tool a sample XML that follows the XSD.

If you just want to do a quick test to see how this works, you can find a simple XSD online and import that. I found this sample which includes an XSD and sample XML that follows the XSD's structure:
https://www.w3schools.com/XML/schema_example.asp

Marc Mundt · Jan 15, 2021 go to post

That's an HL7 vdoc (EnsLib.HL7.Message) and that sample is HL7 code (though with strange delimiters).

So yes, if your input message is HL7 (EnsLib.HL7.Message) then you can just paste a raw HL7 message into the testing tool.

If your input message is XML (EnsLib.EDI.XML.Document) then you can just paste raw XML into the testing tool.

If your input message is an EnsLib.EDI.XML.Document and the message content is HL7 there's going to be a problem :)

Marc Mundt · Jan 15, 2021 go to post

That makes it easy. You can just paste raw XML into the Input Message box in the testing tool.

Marc Mundt · Jan 15, 2021 go to post

What kind of virtual document? What class is the source message -- for example EnsLib.EDI.XML.Document?