Working with Yakov on this, we saw that for SCOPE_IDENTITY() to work on the SQL Serve side it needs to be in the same "scope" of the INSERT (for example in the same Stored Procedure), see here for reference.

So what Yakov ended up doing was encapsulating the INSERT and SELECT SCOPE_IDENTITY() into a Stored Procedure which returns the newly inserted Row ID, and call the SP via the Adapter, thus inserting the new record and getting back the new ID.

Hi Craig,

Perhaps this could help -

From: https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=RSQL_grant

You can use SCHEMA schema-name as the object-list value to grant the object-privilege to all of the tables, views, and stored procedures in the named schema, in the current namespace. For example, GRANT SELECT ON SCHEMA Sample TO Deborah grants this user SELECT privilege for all objects in the Sample schema. This includes all objects that will be defined in this schema in the future. You can specify multiple schemas as a comma-separated list; for example, GRANT SELECT ON SCHEMA Sample,Cinema TO Deborah grants SELECT privilege for all objects in both the Sample and the Cinema schemas.

I'm not sure if I fully understand your question Eduard, but the token itself, internally, is built by the original request's Message Header ID (and the Production name; concatenated with a pipe - |)

E.g., from the code (in Ens.Host):

Method GetDeferredResponseToken(pMessageHeader As Ens.MessageHeader) As %String
{
    Quit pMessageHeader.%Id()_"|"_$$$EnsRuntime("Name")
}

ClassMethod SendDeferredResponse(pDeferredResponseToken As %String, pResponse As %Library.Persistent) As %Status
{
    Set tSC=$$$OK
    Try {
        Set tMessageHeaderId=$p(pDeferredResponseToken,"|",1)
        Set tProductionName=$p(pDeferredResponseToken,"|",2)

Note this is of course internal implementation, and I don't think it is documented or supported (i.e. might change in future versions without notice).

Thanks for filling in the picture Michael.
So this seems to fit into the theory I had about the error indicating your SOAP client is not receiving the response it expected.

You can see the server (the SOAP service) you are turning to is running into an internal error (HTTP status 500) and you also have details about the error they ran into "javax.... " and their relevant stack.

I suggest, if it is possible, that you turn to the entity that is behind this service and report to them the error you are getting (makes sense also to share with them what you see in the log that you are sending to them).

And they might be able to help you.

Hi Michael,

It's a little difficult to tell just from the description you provided what the problem exactly is, but my guesstimate would be that it actually is not related to the encoding (UTF8 vs ISO-8859-1) of what you are sending, but something to do with the response you are getting back.

As the error you quoted mentions - "... returned response with unexpected...".

And specifically the error is complaining about the content-type being text/html where it should probably be expected to be (in the case of SOAP) xml.

So it looks like you provided an extract from the SOAP log - but of what was sent (Output) but not what was received back.

Maybe share that part and we'd be able to help a little more.

You can use (inside %SYS) Config.Namespaces:Get().

For example -

%SYS > set status = ##class(Config.Namespaces).Get("USER",.properties)

%SYS > zwrite properties
properties("Globals")="USER"
properties("Library")="CACHELIB"
properties("Routines")="USER"
properties("SysGlobals")="CACHESYS"
properties("SysRoutines")="CACHESYS"
properties("TempGlobals")="CACHETEMP"
%SYS > set dataDatabaseName = properties("Globals")

%SYS > write dataDatabaseName
USER
%SYS > set codeDatabaseName = properties("Routines")

%SYS > write codeDatabaseName
USER

Of course assuming you are coming from other namespace into %SYS, you can have the name of that namespace in a variable, and use that variable instead of "USER" in my example above.

If you want the actual directory/folder of the database you can also then use Config.Databases:Get(), for example:

%SYS > set status = ##class(Config.Databases).Get("USER",.properties)

%SYS > zwrite properties
properties("ClusterMountMode")=0
properties("Directory")="C:\InterSystems\IRIS\mgr\user\"
properties("MountAtStartup")=0
properties("MountRequired")=0
properties("Server")=""
properties("StreamLocation")=""

And if you want directly just the locations of the databases, and not their names, you could use %SYS.Namespace:GetAllNSInfo() (without having to move into %SYS first) as @Julius Kavay mentioned.

For example:

USER > do ##class(%SYS.Namespace).GetAllNSInfo("USER",.info)

USER > zwrite info
info("GlobalDB","Directory")="c:\intersystems\IRIS\mgr\user\"
info("GlobalDB","Mounted")=1
info("GlobalDB","ReadOnly")=0
info("GlobalDB","Resource")="%DB_USER"
info("GlobalDB","Status")=1
info("GlobalDB","System")=""
info("RoutineDB","Directory")="c:\intersystems\IRIS\mgr\user\"
info("RoutineDB","Mounted")=1
info("RoutineDB","ReadOnly")=0
info("RoutineDB","Resource")="%DB_USER"
info("RoutineDB","Status")=1
info("RoutineDB","System")=""

In line with what @Yaron Munz was saying - when you purge your messages as part of your interoperability data, and you choose to include Message Bodies, then your Body class' data (whether your message body class extends from Ens.Request or Ens.Response, or whether it is simply a class extending from %Persistent) will get deleted together with the Message Header.

The purge code [in Ens.MessageHeader:Purge()] looks at the MessageBodyClassName and MessageBodyId fields of the MessageHeader record and then calls the %DeleteId() method for that class, for the given Id. 

That being said, as @Cristiano Silva pointed out if the class you use as your message body includes references to other persistent classes, these will not get deleted/purged with the referencing object, unless you have an %OnDelete callback method/Trigger taking care of this.

You can see these related posts I shared in the past -

Ran,

Thanks to @Tom Woodfin for finding this - there is a documented limitation for using || within properties that are part of an IDKEY, see from here:

   IMPORTANT:

   There must not be a sequential pair of vertical bars (||) within the values of any property used by an IDKEY index, unless that property is a valid reference to an instance of a persistent class. This restriction is imposed by the way in which the InterSystems SQL mechanism works. The use of || in IDKey properties can result in unpredictable behavior.

And also after some internal discussion - there is no way around this limitation.

You can find in the ENSDEMO "package" (for IRIS, available via Open Exchange here) various sample Productions including for SAP.

Note I believe the sample @Eduard Lebedyuk referred to uses custom Java classes using the PEX approach, and the samples in ENSDEMO use the built-in SAP Java Connector. In both cases SAP JCo is used behind the scenes. And in the 'iris-sap' case also the IDoc support.

If you are creating a FHIR Bundle manually (programmatically; as opposed for example of just getting a Bundle back as a search result response from our built-in FHIR Resource Repository) I think you should be using HS.FHIRServer.Util.Bundle:CreateBundle().

Indeed behind the scenes you can see it calls the CreateGUID() method @Marc Mundt pointed to populate the id -

 Set bundle.id = $ZConvert($SYSTEM.Util.CreateGUID(),"L")

[The $ZConvert changes it to lower-case, e.g.:

USER>set guid = $SYSTEM.Util.CreateGUID()
 
USER>write guid
B990B74D-C008-4F4D-BA3B-4247A740250A
USER>write $ZConvert(guid,"L")
b990b74d-c008-4f4d-ba3b-4247a740250a

]

I actually saw now that the Wizard would work (as per above) also in Ensemble (I tested on v2018.1.x).

The fact that an SQL query just shows the OID, doesn't bother the Wizard to do it's job.

[If you take a peek at the code you can see it generates special stream handling -

 ; STREAMOUT()
 Do rtn.WriteLine("STREAMOUT(oref) {")
  ...
 do rtn.WriteLine(" while (oref.AtEnd = 0) {")
 do rtn.WriteLine(" set len = 32000")
 do rtn.WriteLine(" set val=oref.Read(.len)")
  ...
 do rtn.WriteLine(" write val")
 do rtn.WriteLine(" }")
  ...

]

Nicky,

You can use the %System->%SQL family of audit events.

From the docs:

Event Source Event Type and Event Occurs When Event Data Contents Default Status
%System

%SQL/

DynamicStatement

A dynamic SQL call is executed. The statement text and the values of any host-variable arguments passed to it. If the total length of the statement and its parameters exceeds 3,632,952 characters, the event data is truncated. Off
%System

%SQL/

EmbeddedStatement

An embedded SQL call is executed. See below for usage details. The statement text and the values of any host-variable arguments passed to it. If the total length of the statement and its parameters exceeds 3,632,952 characters, the event data is truncated. Off
%System

%SQL/

XDBCStatement

A remote SQL call is executed using ODBC or JDBC. The statement text and the values of any host-variable arguments passed to it. If the total length of the statement and its parameters exceeds 3,632,952 characters, the event data is truncated. Off

If you're interested only with JDBC you can stick with the last event above (XDBCStatement).

Note, while we're on the subject, if you're looking for "fancier" kind of auditing, for example to log changed fields (before and after values), you can check this thread by @Fabio Goncalves.

For differences between InterSystems CACHE and InterSystems IRIS Data Platform I suggest you have a look here.

Specifically you can find there a table comparing the products (including InterSystems Ensemble).

As well as a document going into detail about various new features and capabilities

If you want to perform a PoC for a new system definitely use InterSystems IRIS.

What is the class name of your Web Service?

Is it also a Business Service? If so - what is the name of the BS component in the Production?

What URL are you using to access this WebService?

I have encountered this error when trying to call the WebService in a way that did not allow Ensemble to understand what is the name of the business service class it needs to use (for example by using the CfgItem URL parameter).

If I understand your question correctly then I think you'd benefit from defining and using a Search Table.

See from the Documentation -

If you need to query specifically via SQL (and not using the Message Viewer) then see also this answer (though relating to HL7, but relevant in the same way to the XML case) regarding using the Search Table within a query.