go to post Brendan Batchelder · Jul 19, 2016 To do this in the message viewer, add an extended criteria to your search parameters. Criterion Type = VDoc Property Path. Class = EnsLib.HL7.Message. DocType = Schema:Name of the type of documents you're searching for (e.g. 2.3.1:ADT_A01). Property Path = the VDoc path of the field you're searching on (e.g. MSH:SendingApplication)It should be noted that the message viewer will use SQL to get a list of messages based on the 'Basic Criteria' and then it loops over the results applying each of the 'Extended Criteria' as a filter. This can be very slow. If it takes more than 2 minutes, the message viewer will time out and either the Basic Criteria needs to be refined in order to return fewer results, or the search for messages must be done with code.To do this with code, use embedded SQL to search on message headers based on basic criteria and then loop over the results checking VDoc paths. Here's an example which looks for messages from a particular day that have a particular value in MSH:3, the Sending Application field: &SQL(DECLARE C1 CURSOR FOR SELECT MessageBodyId INTO :id FROM Ens.MessageHeader WHERE MessageBodyClassName='EnsLib.HL7.Message' AND TimeCreated BETWEEN '2016-07-15' AND '2016-07-16')&SQL(OPEN C1)&SQL(FETCH C1)while (SQLCODE = 0) { set msg = ##class(EnsLib.HL7.Message).%OpenId(id) if (msg.GetValueAt("MSH:SendingApplication") = "Ensemble") { //do something with this message } &SQL(FETCH C1)}&SQL(CLOSE C1)
go to post Brendan Batchelder · Jul 14, 2016 %Ensemble("SessionId") does hold the session id, but by using it you're breaking the abstraction barrier. There's no guarantee that variable name will continue to be used in future versions. Why do you need the SessionId in a DTL? There may be a better way to solve the problem you're trying to solve.
go to post Brendan Batchelder · Jul 7, 2016 In later versions, individual components and their settings can be moved with the Deployment feature in Ensemble. In your staging instance on the production configuration page, select the component you want to move, switch to the 'Actions' tab, and click the 'Export' button. This will allow you to export the code associated with the component along with a .ptd file which contains all of the settings. Then, in the production instance, from the main page of the management portal, go to Ensemble->Manage->Deployment Changes->Deploy and select the xml file you just exported. This will allow you to import the component and all the settings into the production instance without changing anything else in the production class.
go to post Brendan Batchelder · Jul 7, 2016 I saw one of these recently. The programmer was using a target class which had a collection property. His DTL had a loop that was passing the entire target object to a subtransform to have elements added to the collection property, and the result was stored back into target. That subtransform DTL needed to have create=existing to avoid wiping out the target before appending to the collection.
go to post Brendan Batchelder · Jun 22, 2016 I reproduced what you're seeing in latest.If I disable a component via the Production Configuration Page, I see in studio the production class is updated immediately. It automatically refreshes itself within studio.When I disable the component using Ens.Director in terminal, the production class is not updated at all. Even if I close and reopen the production class, it still has the old value.I took a look at the code and it looks like when settings are modified via the Production Configuration page, method SaveToClass in class Ens.Config.Production gets called (near the end of method SaveSettingsToServer in class EnsPortal.ProductionConfig). When Ens.Director method EnableConfigItem is called, there is no call to SaveToClass. I just tested adding that call to the method EnableConfigItem and it worked for me.So you could add code after your call to Ens.Director method EnableConfigItem to open the Ens.Config.Production object and call the SaveToClass method, passing the Ens.Config.Item object for the component that was just enabled/disabled. You can take a look at the EnableConfigItem method to see how it gets the Ens.Config.Production object and the Ens.Config.Item object.
go to post Brendan Batchelder · Jun 22, 2016 You mentioned that when you add a constraint, that's when the rule stops working.Check to make sure the data in your message matches your constraints:In the message body properties, DocTypeCategory should match the rule constraint's docCategory. If they don't match, look at the settings for the business service sending messages to the router and make sure the "Message Schema Category" setting is set correctly.Also make sure the message body's DocTypeName matches the rule constraint's docName.Also make sure the message header's SourceConfigName matches the rule constraint's source.As a side note, when the business service generates the HL7 message object, if the Message Schema Category setting is correct, the service will pull the document type out of MSH:messagetype and store it in DocTypeName for the constraints, so your condition checking MSH:messagetype should be unnecessary. It's checking the same thing as the constraint.
go to post Brendan Batchelder · Jun 21, 2016 This sounds like a job for Health Insight:http://www.intersystems.com/our-products/healthshare/healthshare-product...
go to post Brendan Batchelder · Jun 21, 2016 Thanks for your response. This wasn't a question, but an article to explain to Ensemble programmers how to resend a large number of Ensemble messages. It's not related to semaphores.
go to post Brendan Batchelder · Jun 17, 2016 The REST operation uses adapter EnsLib.HTTP.OutboundAdapter. This adapter class internally uses %Net.HttpRequest method Send to send the http request. That method takes a debug argument telling it to just print the HTTP request rather than sending it to the server. EnsLib.HTTP.OutboundAdapter has a parameter DEBUG which is passed as that debug argument. One thing you could do is temporarily change this parameter to 1 and run the operation in the foreground (only works on windows instances), which will cause the operation to pass that 1 as the debug argument to %Net.HttpRequest method Send. This should print out the request to terminal rather than sending it to the server.
go to post Brendan Batchelder · Jun 8, 2016 One more example: How to call a stored procedure passing a Cache stream as a SQL CLOB: PROCEDURE PUTSTREAM(STREAMIN IN CLOB) IS BEGIN INSERT INTO QUALITY.STREAMTABLE VALUES(STREAMIN); END PUTSTREAM; QUALITY.STREAMTABLE just has one column of type CLOB. Here is the Ensemble Operation code: Method SendStream(pRequest As Ens.StreamContainer, Output pResponse As Ens.Response) As %Status { set TestParams=1 set TestParams(1) = pRequest.Stream set TestParams(1,"SqlType")=$$$SqlLongVarchar //EnsSQLTypes.inc set TestParams(1,"LOB")=1 set QueryStatement = "{ call QUALITY.PUTSTREAM(?) }" set tSC = ..Adapter.ExecuteProcedureParmArray(.ResultSnapshots, .OutputParams, QueryStatement, , .TestParams) Quit tSC }
go to post Brendan Batchelder · Jun 8, 2016 I just wanted to add another example to this. This example shows how to call an oracle stored procedure that uses a SYS_REFCURSOR as an output parameter. CREATE OR REPLACE PROCEDURE "QUALITY"."BRENDANGETCURSORS" ( "ONE" IN DECIMAL, "TWO" OUT SYS_REFCURSOR) IS BEGIN OPEN TWO FOR SELECT * FROM QUALITY.BRENDAN WHERE NUM=ONE; END "BRENDANGETCURSORS"; And the table Quality.Brendan just has a DECIMAL column named NUM and a VARCHAR2 column named STRING Here is the code I used in my Ensemble SQL operation: Method OnMessage(pRequest As Ens.Request, Output pResponse As Ens.Response) As %Status { set tSC = $$$OK set parms=2 set parms(1,"IOType")=$$$SQLPARAMINPUT set parms(1,"SqlType")=$$$SqlDecimal set parms(1,"Prec")=2 set parms(1)=1 set parms(2,"IOType")=$$$SQLPARAMOUTPUT set parms(2,"SqlType")=$$$SqlWLongVarchar set parms(2,"LOB")=0 set sql="{CALL QUALITY.BRENDANGETCURSORS(?,?)}" set rs = ##class(%ListOfObjects).%New() set snap = ##class(EnsLib.SQL.Snapshot).%New() set snap.MaxRowsToGet=10 set tSC = rs.Insert(snap) quit:$$$ISERR(tSC) tSC set tSC=..Adapter.ExecuteProcedureParmArray(.rs,.out,sql,"io",.parms) quit:$$$ISERR(tSC) tSC set snap = rs.GetAt(1) $$$TRACE("Row Count: "_snap.RowCount) $$$TRACE("Column Count: "_snap.ColCount) $$$TRACE("Object? "_$IsObject(snap)) while ('snap.AtEnd) { $$$TRACE("Num: "_snap.Get("Num")) $$$TRACE("String: "_snap.Get("String")) do snap.%Next(.tSC) quit:$$$ISERR(tSC) } quit tSC }
go to post Brendan Batchelder · May 27, 2016 Ensemble provides a tool for generating HTML or PDF documentation for a production. This documentation includes all interfaces and any directories they read from or ports they listen on or ip addresses/ports they connect to, all together in a convenient list.To get to this documentation, on the production configuration page, click the "Production Settings" link which should be just above the Operations column, and then select the actions tab on the right side and there should be a "Document" button.You mentioned you're also looking for the information seen on the production monitor, such as message counts, but in a simpler view. There isn't really a more simple view of this, but if you want to try to use SQL to get the data, I would start with the Ens.MessageHeader table. There is a single Ens.MessageHeader row generated for every message sent from one component to another within a production.