Hello Ruslan, 

You are correct, DisplayToLogical() is not called automatically when saving an object. When you are manipulating an object using ObjectScript, the assumption is that the value you are dealing with is already a logical value. If you need to convert from a display value, you can do so explicitly. For instance, if you have a the following class:

Class Test.MyClass Extends %Persistent
{
Property MyDate As %Date;
}

You can convert from display to internal using either of the following:

set myobj = ##class(Test.MyClass).%New()
set myobj.MyDate = ##class(%Date).DisplayToLogical(value)
set myobj.MyDate = ##class(Test.MyClass).MyDateDisplayToLogical(value)

Hello David,

Can you double check that you have the port forwarding set up correctly when you start the container? This is the error you will get if you try to connect via JDBC to a port that was forwarded to something other than the instance's SuperServer port. The SuperServer port is 1972. For instance, if you start the container with:

docker run -p 51776:1972 -p 52776:52773 containers.intersystems.com/intersystems/iris-community:2020.3.0.221.0

You should be able to connect using the connection string: "jdbc:IRIS://localhost:51776/USER/". In general, you should be able to connect via JDBC to the community edition containers.

Hello Scott,

The error is occurring because Caché does not have the certificate chain needed to verify the certificate used by the remote system. The error is:

Error: 20, unable to get local issuer certificate

The first certificate it is missing is:

Issuer: /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=AAA Certificate Services

The SSL/TLS configuration has been configured to look for trusted certificates in the file: '/ensemble/TestClin/mgr/LDAPKeyStore/OSUWMC_CA.cer'. This should contain all the certificates in the certificate chain needed for the remote certificate, in PEM encoded format. See the documentation here for more information: https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY...

I hope this helps!

Hello, 

In order to use the Web Gateway to dispatch requests to an HTTP Service (such as EnsLib.HL7.Service.HTTPService), we need to have a way for the CSP system to know which Service to dispatch the request to. This works by default if the name of the Service is the same as the class name; in this case CSP can just use the class name in the URL to find the configuration item. It sounds like you already have this working. 

If you have multiple Services in the same production using the same class we need a mechanism to distinguish between them. This can be accomplished using the CfgItem URL parameter. Let's say you have two Services using the "EnsLib.HL7.Service.HTTPService" class, named "HL7ServiceA" and "HL7ServiceB". You can distinguish between them by making requests to the following URLs:

/csp/healthshare/NAMESPACE/EnsLib.HL7.Service.HTTPService.cls?CfgItem=HL7ServiceA

/csp/healthshare/NAMESPACE/EnsLib.HL7.Service.HTTPService.cls?CfgItem=HL7ServiceB

Also note that, in order for any of this to work, the "Enable Standard Requests" setting needs to be enabled for the adapter for each of the Services:

https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=EH...

I hope this helps.

Regards,

Sean Klingensmith

Hi Peter, 

Correlate() simply associates the given XML element with the given ObjectScript class. %XML.Reader allows you to specify multiple element/class associations by calling Correlate() multiple times. Subsequent calls to Next() will return the objects associated with the elements you've correlated, in the order in which they are found in the file. Here is a very basic example using two classes

Here are the classes:

Class Test.A Extends (%RegisteredObject, %XML.Adaptor)
{ 
Property AProp1 As %String(MAXLEN = 64, XMLPROJECTION = "attribute"); 
Property AProp2 As %String(MAXLEN = 64, XMLPROJECTION = "attribute");
}
Class Test.B Extends (%RegisteredObject, %XML.Adaptor)
{ 
Property BProp1 As %String(MAXLEN = 64, XMLPROJECTION = "attribute"); 
Property BProp2 As %String(MAXLEN = 64, XMLPROJECTION = "attribute"); 
}

And our XML file:

<?xml version="1.0" encoding="UTF-8"?>
<objects>
    <A AProp1="abc" AProp2="def"></A>
    <B BProp1="123" BProp2="456"></B>
</objects>

Now we can read both objects in one pass with the following method:

ClassMethod ReadXML()
{
    set reader = ##class(%XML.Reader).%New()
    do reader.OpenFile("/tmp/test.xml")
    
    do reader.Correlate("A", "Test.A")
    do reader.Correlate("B", "Test.B")
    
    do reader.Next(.obj, .sc)
    if $$$ISOK(sc) && $isobject(obj) {
        zwrite obj
    }
    
    do reader.Next(.obj, .sc)
    if $$$ISOK(sc) && $isobject(obj) {
        zwrite obj
    }
}

In a more complex example, you would probably want to call Next() in a loop, and actually pay attention to the error code, but this should demonstrate the point. 

I hope this helps. 

You can configure matching roles in the /csp/ensdemo Web Application for the custom role you created previously. This would allow you to grant additional privileges, only to the users belonging to the custom role, and only when those users are in this CSP Application.

See the documentation for Matching Roles for more details.

I think the only additional resources you should need (by default) are %DB_ENSDEMO, and %Ens_Portal. You need %Ens_Portal because that is the resource required for the /csp/ensdemo application.

Hello Gery,

There are a couple of ways to do this. Ultimately, what you want is to define a Resource (say my_soap_resource) that controls access to the Web Service, or the CSP Application. You can then create a Role to grant access to that Resource, and assign the Role to your user. For more information on Resources and Roles, see the Caché Security Administration Guide.

Once you have created the Resource, you can use it to control access either to the entire Web Application, or to the individual SOAP Service. You would configure this in the CSP Application if you had a set of pages/Web Services, and you wanted to control access to them by the same resource. If you want more granular control, you can configure the individual page to require this resource.

To configure this at the Web Application level, go to the Web Application definition in the Management Portal:

[System Administration]->[Security]->[Applications]->[Web Applications]

and set your resource (my_soap_resource) in the "Resource Required" field.

To configure access for the individual SOAP service, edit the Test.BS.WSService class, and add the following parameter:

Parameter SECURITYRESOURCE = 'my_soap_resource';

Once this is done, only users with access to this resource will be able to access this SOAP Service. Other users will receive the error: "Illegal CSP Request". There are a couple of things to note:

1) Users will need this resource to do anything with this Web Service, including accessing the WSDL.

2) Users with the %All Role will have permissions on all Resources, so they will be able to access the Web Service, even without being assigned to your custom Role.

3) These restrictions only apply when accessing the Web Service through the CSP Gateway (EnableStandardRequests). When accessing the Web Service through the custom Adapter port, these setting will be ignored. (see the documentation for the SOAP adapter settings).

Hello,

The code you included will return a SOAP fault to the client with the specified fault code and message. Since this is a Business Service, it will also log the fault to the Ensemble Event Log, along with the last error the process encountered (%objlasterror). This appears to be where this is where the error message is coming from.

Note that, again, since this is a Business Service, you can use the ReturnStatusFault() or ReturnMethodStatusFault() methods to create and return the SOAP fault instead of creating it manually. This should have the same behavior as your code, except that the fault code and message may be different. See the documentation here:

http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

I'm not really sure that I answered your question. Can you give more information about the problem you are trying to solve?

Hello Rajath,

In addition to what John said, it is always advisable to check the value of SQLCODE after running an embedded SQL statement. This will tell you if the SQL statement executed successfully, or encountered an error. If it encountered an error, you can get more details from the %msg variable. See the documentation here:

http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

You said that you are getting a JavaScript error. What is the error message? Can you send the JavaScript code you are using to call the retrieveDetail() function?

Hello Laura,

The CSP.Daemon will use the CSP Event classes (there can be more than one) associated with the session (this information is stored in the ^%cspSession global). It will default to the value of the Event Class setting in the CSP Application, but, as you know, it can also be set programmatically. 

/isc/studio/usertemplates/ is a CSP Application used by Studio to display certain dialogs. I don't believe we take a license for these sessions, but they should still time out. 

It looks like the CSP.Daemon is failing to end these sessions. This investigation might get a fairly involved. I definitely recommend contacting the WRC with the information mentioned above. 

Hello Laura,

If the user logs out with CacheLogout=end, or %session.EndSession=1, the session will end OnEndSession callback will be called and the session will be terminated immediately, and the license will be released. This will be done in the CSP server process, not the CSP.Daemon.

If the user closes the window (or just walks away from the computer), the session and the license will remain until the session timeout is reached. This is done by the the CSP.Daemon, which will periodically wake up and look for sessions that have expired, and end them. Setting EndSession=0 in the callback would prevent the session from being ended. As long as this has been removed, I agree, the CSP.Daemon should be cleaning these sessions up. 

Are you able to end any of these sessions through the Management Portal page? (I'm not recommending deleting all of them, this is just a diagnostic test). 

If you open a WRC Case, I recommend sending:

1) a Buttons report

2) an export of the Session Events class (just in case)

3) an export of the ^%cspSession global:

do $system.OBJ.Export("%cspSession.gbl","/tmp/cspSession.xml")

The CSP.Daemon should close any session with a timeout in the past. Do you have CSP Events class? In my experience, the most common cause of problems like this is a misbehaving OnTimeout or OnEndSession callback, but there could be other causes. 

If there isn't anything obviously wrong with the callback code, I suggest you open a WRC case to investigate this. 

Regards,

Sean Klingensmith

Hello Laura,

Do you see any CSP Sessions active under [System Operation]->[CSP Sessions]? The CSP.Daemon will end any sessions (and release the associated license) after the session times out. The timeout for each session will be displayed on this page. You can also manually end sessions. 

If the license is remaining after the CSP Session is ended, or if the session remains after it is supposed to be timed out this would indicate a problem with the session reclamation. Otherwise, it could be an issue with an excessively long session timeout (this can be configured in the CSP Application).